Changeset 2563515
- Timestamp:
- 07/13/2021 12:17:00 PM (5 years ago)
- Location:
- pmpro-import-members-from-csv
- Files:
-
- 8 added
- 2 deleted
- 50 edited
- 1 copied
-
tags/v3.0.6 (copied) (copied from pmpro-import-members-from-csv/trunk)
-
tags/v3.0.6/ActivateUtilitiesPlugin.php (deleted)
-
tags/v3.0.6/CHANGELOG.md (modified) (4 diffs)
-
tags/v3.0.6/README.md (added)
-
tags/v3.0.6/README.txt (modified) (12 diffs)
-
tags/v3.0.6/build_config (added)
-
tags/v3.0.6/build_config/plugin_config.mk (added)
-
tags/v3.0.6/class-activateutilitiesplugin.php (added)
-
tags/v3.0.6/class.pmpro-import-members.php (modified) (4 diffs)
-
tags/v3.0.6/docker-compose.yml (modified) (2 diffs)
-
tags/v3.0.6/javascript/pmpro-import-members-from-csv.js (modified) (1 diff)
-
tags/v3.0.6/src/class-data.php (modified) (3 diffs)
-
tags/v3.0.6/src/class-email-templates.php (modified) (4 diffs)
-
tags/v3.0.6/src/class-error-log.php (modified) (2 diffs)
-
tags/v3.0.6/src/class-import-members.php (modified) (5 diffs)
-
tags/v3.0.6/src/class-variables.php (modified) (3 diffs)
-
tags/v3.0.6/src/import/class-ajax.php (modified) (13 diffs)
-
tags/v3.0.6/src/import/class-csv.php (modified) (8 diffs)
-
tags/v3.0.6/src/modules/BuddyPress/class-buddypress.php (modified) (3 diffs)
-
tags/v3.0.6/src/modules/BuddyPress/class-column-validation.php (modified) (7 diffs)
-
tags/v3.0.6/src/modules/BuddyPress/class-import-buddypress.php (modified) (1 diff)
-
tags/v3.0.6/src/modules/PMPro/class-column-validation.php (modified) (22 diffs)
-
tags/v3.0.6/src/modules/PMPro/class-import-member.php (modified) (13 diffs)
-
tags/v3.0.6/src/modules/PMPro/class-import-sponsors.php (modified) (9 diffs)
-
tags/v3.0.6/src/modules/PMPro/class-pmpro.php (modified) (1 diff)
-
tags/v3.0.6/src/modules/PMPro/class-sponsor.php (modified) (8 diffs)
-
tags/v3.0.6/src/modules/Users/class-column-validation.php (modified) (4 diffs)
-
tags/v3.0.6/src/modules/Users/class-import-user.php (modified) (2 diffs)
-
tags/v3.0.6/src/modules/Users/class-user-validation.php (modified) (5 diffs)
-
tags/v3.0.6/src/validate/class-base-validation.php (modified) (4 diffs)
-
tags/v3.0.6/src/validate/class-date-format.php (modified) (2 diffs)
-
trunk/ActivateUtilitiesPlugin.php (deleted)
-
trunk/CHANGELOG.md (modified) (4 diffs)
-
trunk/README.md (added)
-
trunk/README.txt (modified) (12 diffs)
-
trunk/build_config (added)
-
trunk/build_config/plugin_config.mk (added)
-
trunk/class-activateutilitiesplugin.php (added)
-
trunk/class.pmpro-import-members.php (modified) (4 diffs)
-
trunk/docker-compose.yml (modified) (2 diffs)
-
trunk/javascript/pmpro-import-members-from-csv.js (modified) (1 diff)
-
trunk/src/class-data.php (modified) (3 diffs)
-
trunk/src/class-email-templates.php (modified) (4 diffs)
-
trunk/src/class-error-log.php (modified) (2 diffs)
-
trunk/src/class-import-members.php (modified) (5 diffs)
-
trunk/src/class-variables.php (modified) (3 diffs)
-
trunk/src/import/class-ajax.php (modified) (13 diffs)
-
trunk/src/import/class-csv.php (modified) (8 diffs)
-
trunk/src/modules/BuddyPress/class-buddypress.php (modified) (3 diffs)
-
trunk/src/modules/BuddyPress/class-column-validation.php (modified) (7 diffs)
-
trunk/src/modules/BuddyPress/class-import-buddypress.php (modified) (1 diff)
-
trunk/src/modules/PMPro/class-column-validation.php (modified) (22 diffs)
-
trunk/src/modules/PMPro/class-import-member.php (modified) (13 diffs)
-
trunk/src/modules/PMPro/class-import-sponsors.php (modified) (9 diffs)
-
trunk/src/modules/PMPro/class-pmpro.php (modified) (1 diff)
-
trunk/src/modules/PMPro/class-sponsor.php (modified) (8 diffs)
-
trunk/src/modules/Users/class-column-validation.php (modified) (4 diffs)
-
trunk/src/modules/Users/class-import-user.php (modified) (2 diffs)
-
trunk/src/modules/Users/class-user-validation.php (modified) (5 diffs)
-
trunk/src/validate/class-base-validation.php (modified) (4 diffs)
-
trunk/src/validate/class-date-format.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
pmpro-import-members-from-csv/tags/v3.0.6/CHANGELOG.md
r2555218 r2563515 6 6 7 7 ## [Unreleased] 8 9 ## v3.0.6 - 2021-07-13 10 - BUG FIX: Updates to presence check for test types (Thomas Sjolshagen) 11 - BUG FIX: Didn't install the ruleset when in GitHub Action (Thomas Sjolshagen) 12 - BUG FIX: Fatal error during install of production composer dependencies (Thomas Sjolshagen) 13 - BUG FIX: acceptance-test target didn't work (Thomas Sjolshagen) 14 - BUG FIX: TTYs in docker-compose.yml (Thomas Sjolshagen) 15 - BUG FIX: Adding a stripped down data file for the WP Unit tests (Thomas Sjolshagen) 16 - BUG FIX: Refactor of the Makefile (Thomas Sjolshagen) 17 - BUG FIX: Didn't exclude inc/ in codeception.dist.yml (Thomas Sjolshagen) 18 - BUG FIX: Handle DB Dump if present (Thomas Sjolshagen) 19 - BUG FIX: Reverted inclusion of SQL file in repo (Thomas Sjolshagen) 20 - BUG FIX: Wrong path to the DB file we need for testing (Thomas Sjolshagen) 21 - BUG FIX: Add Docker Hub login to release-plugin.yml (Thomas Sjolshagen) 22 - BUG FIX: Include SQL so it can be used by WP Unit ++ tests (Thomas Sjolshagen) 23 - BUG FIX: Fix issue with TTY during GitHub action execution (Thomas Sjolshagen) 24 - BUG FIX: Adding COMPOSE_INTERACTIVE_NO_CLI=1 to work around 'The input device is not a TTY' errors/warnings (Thomas Sjolshagen) 25 - BUG FIX: Make sure we use the correct Docker Hub login approach (Thomas Sjolshagen) 26 - BUG FIX: Use log file if it's available (Thomas Sjolshagen) 27 - BUG FIX: Use action recipe for docker hub login (Thomas Sjolshagen) 28 - BUG FIX: More testing of docker hub login (Thomas Sjolshagen) 29 - BUG FIX: Split remote and local removal of tags (Thomas Sjolshagen) 30 - BUG FIX: Updates to debug Docker Hub login issues (Thomas Sjolshagen) 31 - BUG FIX: Make sure the file check works w/o error as a GitHub action (Thomas Sjolshagen) 32 - BUG FIX: Revert the shell based check for phpcs presence (shouldn't be needed) (Thomas Sjolshagen) 33 - BUG FIX: Troubleshooting the Makefile (Thomas Sjolshagen) 34 - BUG FIX: Use BASH by default when running commands (Thomas Sjolshagen) 35 - BUG FIX: Clean up PHONY targets and enable curl output (Thomas Sjolshagen) 36 - BUG FIX: Add PHPStan testing (Thomas Sjolshagen) 37 - BUG FIX: Enable parallel execution for PHPStan and omit a couple of error types (Thomas Sjolshagen) 38 - BUG FIX: PHPStan fixes to handle different versions of the Licensing module (Thomas Sjolshagen) 39 - BUG FIX: PHPStan related fixes in the Users class-column-validation.php file (Thomas Sjolshagen) 40 - BUG FIX: PHPStan related fixes in class-import-sponsors.php (Thomas Sjolshagen) 41 - BUG FIX: Incomplete argument type definition for Sponsor::get() method (Thomas Sjolshagen) 42 - BUG FIX: PHPStan related fixes in the PMPro class-import-member.php file (Thomas Sjolshagen) 43 - BUG FIX: Various logic and PHPStan related fixes in the PMPro class-column-validation.php file (Thomas Sjolshagen) 44 - BUG FIX: Various PHPStan related fixes in the BuddyPress class-column-validation.php file (Thomas Sjolshagen) 45 - BUG FIX: Various PHPStan related fixes for class-csv.php (Thomas Sjolshagen) 46 - BUG FIX: Remove unneeded exit() calls - PHPStan fixes for class-ajax.php (Thomas Sjolshagen) 47 - BUG FIX: Incorrect PHPStan errors for add_filter() function (Thomas Sjolshagen) 48 - BUG FIX: The $id parameter wasn't defined for all code paths in class-import-user.php (Thomas Sjolshagen) 49 - BUG FIX: Fixed PMPro related ignore/revert ignore comments in class-email-templates.php (Thomas Sjolshagen) 50 - BUG FIX: Ignored a PHPStan non-error in class-data.php (Thomas Sjolshagen) 51 - BUG FIX: Return value in PHPDoc wrong for load_actions() method (Thomas Sjolshagen) 52 - BUG FIX: PHPStan fixes for class-base-validation.php (Thomas Sjolshagen) 53 - BUG FIX: PHPStan fixes for class-activateutilitiesplugin.php (Thomas Sjolshagen) 54 - BUG FIX: Fatal errors due to poor error recovery in autoloader (Thomas Sjolshagen) 55 - BUG FIX: Clean up config for phpstan-test target (Thomas Sjolshagen) 56 - BUG FIX: code-standards-test target depends on plugin and composer modules (Thomas Sjolshagen) 57 - BUG FIX: Add WP Neutron code standards config (Thomas Sjolshagen) 58 - BUG FIX: PHPCS ignored some of the plugin source files (Thomas Sjolshagen) 59 - BUG FIX: Add WP Neutron code standards config (Thomas Sjolshagen) 60 - BUG FIX: Code sniffer updates for Buddypress version of class-column-validation.php (Thomas Sjolshagen) 61 - BUG FIX: Code sniffer updates for class-buddypress.php (Thomas Sjolshagen) 62 - BUG FIX: Code sniffer updates for class-import-buddypress.php (Thomas Sjolshagen) 63 - BUG FIX: Code sniffer updates for class-import-member.php (Thomas Sjolshagen) 64 - BUG FIX: Code sniffer updates for class-pmpro.php (Thomas Sjolshagen) 65 - BUG FIX: Code sniffer updates for class-ajax.php (Thomas Sjolshagen) 66 - BUG FIX: Code sniffer updates for class-column-validation.php (Thomas Sjolshagen) 67 - BUG FIX: Include the ActivateUtilitiesPlugin class path and clean up paths to scan/include (Thomas Sjolshagen) 68 - BUG FIX: PHPStan test execution settings (Thomas Sjolshagen) 69 - BUG FIX: Didn't autoload classes we expected to load (Thomas Sjolshagen) 70 - BUG FIX: PHPStan test command updated, making sure the inc/wp_plugins dir exists, and more info for some of the testing tagets (Thomas Sjolshagen) 71 - BUG FIX: php-composer target didn't work and phpstan memory limit set to 'unlimited' (Thomas Sjølshagen) 72 - BUG FIX: Renamed deps to wp-deps (Thomas Sjolshagen) 73 - BUG FIX: per_partial is an integer and not a float (Thomas Sjolshagen) 74 - BUG FIX: PHPStan test doesn't need a docker container to run (Thomas Sjolshagen) 75 - BUG FIX: PHPStan errors we don't care about (PMPro functions / class members, etc) (Thomas Sjolshagen) 76 - BUG FIX: PHPStan errors we don't care about (Thomas Sjolshagen) 77 - BUG FIX: PHPDoc string was incorrect (Thomas Sjolshagen) 78 - BUG FIX: Fatal error because we attempted to use Data::get_instance() plus PHPCS nits (Thomas Sjolshagen) 79 - BUG FIX: PHPStan complained about require_once call for Utility loader (Thomas Sjolshagen) 80 - BUG FIX: Make config more dynamic for testing (Thomas Sjolshagen) 81 - BUG FIX: Fix config for PHPStan testing (Thomas Sjolshagen) 82 - BUG FIX: Updates in support of PHPStan testing (Thomas Sjolshagen) 83 - BUG FIX: User Validation class was only partially implemented (Thomas Sjolshagen) 84 - BUG FIX: Wrong file name for plugin file (Thomas Sjolshagen) 85 - BUG FIX: Re-inverted the DOWNLOAD logic (Thomas Sjolshagen) 86 - BUG FIX: Use the get_plugin_version.sh script (Thomas Sjolshagen) 87 - BUG FIX: Made the wrong assumption about the location of the Version string (Thomas Sjolshagen) 88 - BUG FIX: Clean up build vs download for E20R plugins (Thomas Sjolshagen) 89 - BUG FIX: Refactored utility module build process (Thomas Sjolshagen) 90 - BUG FIX: Refactored build target (Thomas Sjolshagen) 91 - BUG FIX: More errors when determining local presence for Utilities (Thomas Sjolshagen) 92 - BUG FIX: Annoying errors in the Makefile (including -z vs -n issues) (Thomas Sjolshagen) 93 - BUG FIX: Build target updates to be .php file change triggered (Thomas Sjolshagen) 94 - BUG FIX: Wrong build target for custom E20R modules (Thomas Sjolshagen) 95 - BUG FIX: Utilities module dependency build fixes (Thomas Sjolshagen) 96 - BUG FIX: Didn't handle when Utilities module is in local git repo (Thomas Sjolshagen) 97 98 ## v3.0.5 - 2021-07-05 99 - BUG FIX: Reformatted README.md (Thomas Sjolshagen) 100 - BUG FIX: Duplicate entries in CHANGELOG.md (Thomas Sjolshagen) 101 - BUG FIX: Using template for metadata.json (Thomas Sjolshagen) 102 - BUG FIX: Build script for readme files updated (Thomas Sjolshagen) 103 - BUG FIX: Typo and formatting updates (Thomas Sjolshagen) 104 - BUG FIX: Don't clean up E20R custom plugins unless in one of the clean-up targets (Thomas Sjolshagen) 105 - BUG FIX: Unit tests do not require WordPress (Thomas Sjolshagen) 106 - BUG FIX: Wrong path for database container volume (Thomas Sjolshagen) 107 - BUG FIX: Typo in comments (Thomas Sjolshagen) 108 - BUG FIX: Old file name for plugin activation of 00-e20r-utilities (Thomas Sjolshagen) 109 - BUG FIX: Missing class definition for assertEquals() call in class-csv-UnitTest.php and class-import-members-UnitTest.php (Thomas Sjolshagen) 110 - BUG FIX: Errors when building the 00-e20r-utilities plugin as a dependency and add clean-up target (Thomas Sjolshagen) 111 - BUG FIX: Simplify config of make/build scripts (Thomas Sjolshagen) 112 - BUG FIX: Potentially inconsistent port use in test environment (Thomas Sjolshagen) 113 - BUG FIX: Initial commit - extracts version info for plugin (Thomas Sjolshagen) 114 - BUG FIX: Shift to PHPUnit 8.x (from 9.x) (Thomas Sjolshagen) 115 - BUG FIX: Use local repo to build 00-e20r-utilities plugin when possible (Thomas Sjolshagen) 116 - BUG FIX: Fixed the WP Unit test suite config for Codeception testing (Thomas Sjolshagen) 117 - BUG FIX: Pasted the wrong path to the Docker key file (Thomas Sjolshagen) 118 - BUG FIX: Be explicit about priorities and args when loading filter/action hooks (Thomas Sjolshagen) 119 - BUG FIX: Setting to handle WP's multi-site testing (Thomas Sjolshagen) 120 - BUG FIX: Use configurable vendor directory for composer (Thomas Sjolshagen) 121 - BUG FIX: Didn't account for the different possibilities for the Utilities/Licensing module (Thomas Sjolshagen) 122 - BUG FIX: A bit too aggressive when clearing inc/ directory (Thomas Sjolshagen) 123 - BUG FIX: Use custom gitignore file for inc/ directory (Thomas Sjolshagen) 124 - BUG FIX: Change log script fixed to avoid duplicate entries, blank line errors, etc (Thomas Sjolshagen) 125 - BUG FIX: Fixed the messed up autoloader and coding standard errors (Thomas Sjolshagen) 126 - BUG FIX: Removed unneeded variables in Makefile (Thomas Sjolshagen) 127 - BUG FIX: Refactored Makefile to be a bit more generic (Thomas Sjolshagen) 128 - BUG FIX: Update data file location for manual testing (Thomas Sjolshagen) 129 - BUG FIX: Renamed ActivateUtilitiesPlugin.php to fix coding standards errors (Thomas Sjolshagen) 130 - BUG FIX: Fix Coding Standard errors in class.pmpro-import-members.php (Thomas Sjolshagen) 131 - BUG FIX: Fix Coding Standard errors in class-validate.php (Thomas Sjolshagen) 132 - BUG FIX: Fix Coding Standard errors in class-date-format.php (Thomas Sjolshagen) 133 - BUG FIX: Fix Coding Standard problems (Thomas Sjolshagen) 134 - BUG FIX: Handle exporting the plugin as a git archive (Thomas Sjolshagen) 135 - BUG FIX: Calculated the wrong timeout value for the JS based background import (Thomas Sjolshagen) 136 - BUG FIX: Updated copyright notice (Thomas Sjolshagen) 137 - BUG FIX: PHPCS was a bit too inclusive (Thomas Sjolshagen) 138 - BUG FIX: Include the README.md file (Thomas Sjolshagen) 139 - BUG FIX: Relocate build status badge (Thomas Sjolshagen) 140 - BUG FIX: Splitting log/doc/updater json generation further (Thomas Sjolshagen) 141 - BUG FIX: Updated CHANGELOG (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 142 - BUG FIX: Error generating documentation (Thomas Sjolshagen) 143 - BUG FIX: Use command for git (Thomas Sjolshagen) 144 - BUG FIX: Updating changelog source (Thomas Sjolshagen) 145 - BUG FIX: Reverted CHANGELOG status (Thomas Sjolshagen) 146 - BUG FIX: Separate CHANGELOG and README file generation (Thomas Sjolshagen) 147 - BUG FIX: Updated version number (v3.0.5) (Thomas Sjolshagen) 148 - BUG FIX: Create README.md from the README.txt file (Thomas Sjolshagen) 149 - BUG FIX: Separate CHANGELOG and README file generation (Thomas Sjolshagen) 150 - BUG FIX: Updated README info (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 151 - BUG FIX: Updated version (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 152 - BUG FIX: Didn't include a README.md file for the plugin (Thomas Sjolshagen) 153 - BUG FIX: Update repository name (Thomas Sjolshagen) 154 - BUG FIX: Action triggered twice (Thomas Sjolshagen) 155 - Bug fix/remove debug logging (#6) (Thomas Sjølshagen) 156 - BUG FIX: Re-activate the installed_paths setting for phpcs (Thomas Sjolshagen) 8 157 9 158 ## v3.0.4 - 2021-06-28 … … 151 300 - BUG FIX: Added action hook documentation (Thomas Sjolshagen) 152 301 - BUG FIX: Fix PHPCS warnings (Thomas Sjolshagen) 153 - BUG FIX: Fix PHPCS warnings (Thomas Sjolshagen)154 302 - BUG FIX: Rename e20r_import_load_licensed_modules action hook (Thomas Sjolshagen) 155 303 - BUG FIX: Rename e20r_import_load_licensed_modules action hook and fix PHPCS warnings (Thomas Sjolshagen) … … 224 372 - BUG FIX: Refactored docker-compose.override files for manual testing (Thomas Sjolshagen) 225 373 - BUG FIX: Adding/Updating *ignore files (Thomas Sjolshagen) 226 - BUG FIX: Adding/Updating *ignore files (Thomas Sjolshagen)227 374 - BUG FIX: More updates to support WP Unit testing (Thomas Sjolshagen) 228 375 - BUG FIX: Various updates to support WordPress 'Unit' testing (Thomas Sjolshagen) … … 491 638 * Fixed bugs with static/non-static function calls 492 639 * Enhancement: JavaScript based async loading (for large imports) 640 - BUG FIX: Calculated the wrong timeout value for the JS based background import (Thomas Sjolshagen) 641 - BUG FIX: Updated copyright notice (Thomas Sjolshagen) 642 - BUG FIX: PHPCS was a bit too inclusive (Thomas Sjolshagen) 643 - BUG FIX: Include the README.md file (Thomas Sjolshagen) 644 - BUG FIX: Relocate build status badge (Thomas Sjolshagen) 645 - BUG FIX: Splitting log/doc/updater json generation further (Thomas Sjolshagen) 646 - BUG FIX: Updated CHANGELOG (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 647 - BUG FIX: Error generating documentation (Thomas Sjolshagen) 648 - BUG FIX: Use command for git (Thomas Sjolshagen) 649 - BUG FIX: Updating changelog source (Thomas Sjolshagen) 650 - BUG FIX: Reverted CHANGELOG status (Thomas Sjolshagen) 651 - BUG FIX: Separate CHANGELOG and README file generation (Thomas Sjolshagen) 652 - BUG FIX: Updated version number (v3.0.5) (Thomas Sjolshagen) 653 - BUG FIX: Create README.md from the README.txt file (Thomas Sjolshagen) 654 - BUG FIX: Separate CHANGELOG and README file generation (Thomas Sjolshagen) 655 - BUG FIX: Updated README info (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 656 - BUG FIX: Updated version (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 657 - BUG FIX: Didn't include a README.md file for the plugin (Thomas Sjolshagen) 658 - BUG FIX: Update repository name (Thomas Sjolshagen) 659 - BUG FIX: Action triggered twice (Thomas Sjolshagen) 660 - Bug fix/remove debug logging (#6) (Thomas Sjølshagen) 661 - BUG FIX: Re-activate the installed_paths setting for phpcs (Thomas Sjolshagen) -
pmpro-import-members-from-csv/tags/v3.0.6/README.txt
r2555218 r2563515 4 4 Requires at least: 5.0 5 5 Tested up to: 5.7.2 6 Stable tag: 3.0. 46 Stable tag: 3.0.6 7 7 License: GPLv2 8 8 License URI: http://www.gnu.org/licenses/gpl 9 9 10 Import and create user + PMPro member records from a CSV file to your WordPress with Paid Memberships Pro website. Can import the membership information, user meta data, PMPro order data and will link any pre-existing recurring payment records for your payment gateway integration. 10 [](https://github.com/eighty20results/pmpro-import-members-from-csv/actions/workflows/release-plugin.yml) 11 12 Import and create user + PMPro member records from a CSV file on your WordPress with Paid Memberships Pro website. 13 The plugin will import the membership information, user meta data, PMPro order data, Sponsored Members information and 14 can even link pre-existing recurring payment records for your payment gateway integration. 11 15 12 16 == Description == 13 17 14  15 16 This plugin is designed to give you an error free import of a user/member to a WordPress/Paid Memberships Pro site. It supports both adding and changing user data. 17 18 Unlike the "Import User From CSV Integration" add-on by Paid Memberships Pro, this "Import Members from CSV" plugin will verify the data you are trying to import during the import operation. This is done to reduce the probability of problem after the import. If there are any errors/issues,information about the problem will be logged to the pmp_updates.log saved in the `wp-content/uploads/` directory. 19 20 *NOTE*: You can run the import multiple times with the same/slightly modified import .csv file and the appropriate settings (see the FAQ/description below). If you configure the plugin settings correctly, this will only result in overwriting/changing the existing member data. 21 22 Using a CSV (Comma Separated Values) file, the will add users with basic user information as well as user meta data fields, the user role (if applicable) and the specified Paid Memberships Pro member configuration/information. It can also generate an order record to ensure your recurring subscriptions continue to get attributed to the imported member. 23 24 If you've exported the user's passwords as hashed strings, you can import them without re-encrypting them again (by setting the option). 18 We designed this plugin to give you an error free import of a user/member to a WordPress/Paid Memberships Pro site. 19 It supports both adding and changing user data. 20 21 Unlike the "Import User From CSV Integration" add-on by Paid Memberships Pro, this "Import Members from CSV" plugin 22 will verify the data you are trying to import during the import operation. This is done to reduce the probability of 23 problem after the import. If there are any errors/issues, information about the problem will be logged to the 24 `e20r_im_errors.log` saved in the `wp-content/uploads/` directory. 25 26 **NOTE**: You can run the import multiple times with the same/slightly modified import .csv file and the appropriate 27 settings (see the FAQ/description below). If you configure the plugin settings correctly, this will only result in 28 overwriting/changing the existing member data. 29 30 Using a CSV (Comma Separated Values) file, the will add users with basic user information as well as user meta data 31 fields, the user role (if applicable) and the specified Paid Memberships Pro member configuration/information. It can 32 also generate an order record to ensure your recurring subscriptions continue to get attributed to the imported member. 33 34 If you've exported the user's passwords as hashed strings, you can import them without re-encrypting them again 35 (by setting the option). 25 36 26 37 You can also choose to send a notification to the new users and to display password nag on user login. 27 38 28 This plugin supports Network Activation on a WordPress Multisite (WPMU) installation (see the settings page when using in a multisite configuration) 39 This plugin supports Network Activation on a WordPress Multisite (WPMU) installation (see the settings page when 40 using in a multisite configuration) 41 29 42 [Check out my other plugins.](http://eighty20results.com/wordpress-plugins/) 30 43 … … 43 56 * Import hashed password for new/updating users (if the option is selected) 44 57 45 *NOTE*: The plugin may not import some of data if it detects a problem. To find out what the problem was, read this documentation and the FAQ section to ensure you have correctly formatted _all_ of your import data. 46 47 For feature request and bug reports, [please use the issues section on GitHub](https://github.com/eighty20results/import-members-from-csv/issues). 48 Code contributions are welcome [on Github](https://github.com/eighty20results/import-members-from-csv). 49 50 NOTE: In order to hide the "Donation" button after a donation, this plugin will attempt to track the admin's IP address. This action may have GDPR implications for you or your administrators. 51 52 The tracking information is stored in the WordPress options table (wp_options) using the `e20r_import_has_donated` option name and can safely be deleted in the database if you do not wish to leave it. Deleting the option from the database will obviously re-enable the Donation nag. 58 **NOTE**: The plugin may not import some of data if it detects a problem. To find out what the problem was, read this 59 documentation and the FAQ section to ensure you have correctly formatted _all_ of your import data. 60 61 For feature request and bug reports, [please use the issues section on GitHub](https://github.com/eighty20results/pmpro-import-members-from-csv/issues). 62 Code contributions are welcome [on Github](https://github.com/eighty20results/pmpro-import-members-from-csv). 63 64 **NOTE**: In order to hide the "Donation" button after a donation, this plugin will attempt to track the admin's IP 65 address. This action may have GDPR implications for you or your administrators. 66 67 The tracking information is stored in the WordPress options table (wp_options) using the `e20r_import_has_donated` 68 option name and can safely be deleted in the database if you do not wish to leave it. Deleting the option from the 69 database will obviously re-enable the Donation nag. 53 70 54 71 The Nag tracking can be disabled altogether with the `e20r_import_donation_tracking_disabled` filter: … … 68 85 Or use a nifty tool by WordPress lead developer Mark Jaquith: 69 86 70 1. Visit [this link](http://coveredwebservices.com/wp-plugin-install/?plugin=pmpro-import-members-from-csv) and follow the instructions. 87 1. Visit [this link](http://coveredwebservices.com/wp-plugin-install/?plugin=pmpro-import-members-from-csv) and 88 follow the instructions. 71 89 72 90 … … 83 101 1. Upload your CSV file in the 'Memberships' menu, under 'Import Members' 84 102 85 = = Frequently Asked Questions ==86 87 = How to use?=103 = Frequently Asked Questions = 104 105 == How to use? == 88 106 89 107 Click on the 'Import Members' link in the 'Membership' menu, then select your CSV file. 90 108 Next you have to decide whether you: 91 109 92 1. want to deactivate previously existing member record(s) for the user - The CSV record has to specify the same membership as the user previously had so this is most useful when having to reimport/update data (default: enabled and recommended), 93 1. update the existing user/member's information (default: enabled and recommended) 94 1. send a notification email to new users (default: disabled), 95 1. want the password nag to be displayed when the user logs in (default: disabled), 96 1. have included a hashed (encoded) password specified in the import file and (default: disabled) 97 1. want to use the background import option (default: enabled and recommended) 98 1. create a PMPro order record based on supplied payment info in the .csv file (default: disabled) 110 1. want to deactivate previously existing member record(s) for the user - The CSV record has to specify the same 111 membership as the user previously had so this is most useful when having to reimport/update data (default: enabled and 112 recommended), 113 2. update the existing user/member's information (default: enabled and recommended) 114 3. send a notification email to new users (default: disabled), 115 4. want the password nag to be displayed when the user logs in (default: disabled), 116 5. have included a hashed (encoded) password specified in the import file and (default: disabled) 117 6. want to use the background import option (default: enabled and recommended) 118 7. create a PMPro order record based on supplied payment info in the .csv file (default: disabled) 99 119 100 120 Then click the 'Import' button. 101 121 102 122 Each row in your CSV file should represent a user; each column identifies user data, user meta data or user membership data 103 If a column name matches a field in the user table, data from this column is imported in that field; if not, data is imported in a user meta field with the name of the column or into the PMPro custom membership tables. 104 105 Look at the examples/import.csv file in the plugin directory (also linked on the "Import Members" page) to have a better understanding of how the your CSV file should be organized and what the data fields need to contain as far as formatting/values go. 106 107 You can always try importing the examples/import.csv file and look at the result, assuming the values specified for the membership_id in the example file match your membership level configuration. 108 109 = The .CSV file from the "Export to CSV" button on the "Members List" page won't import? = 110 111 The purpose of the resulting .CSV file from the "Export to CSV" is to generate reports that are meaningful to a human, not a file that can be imported easily. This is true for any of the available Import from .CSV plugins/add-ons for Paid Memberships Pro. 112 113 Basically there are a few key differences between the file resulting from the Export function and the file contents needed to import the same member. 123 If a column name matches a field in the user table, data from this column is imported in that field; if not, data is 124 imported in a user meta field with the name of the column or into the PMPro custom membership tables. 125 126 Look at the examples/import.csv file in the plugin directory (also linked on the "Import Members" page) to have a 127 better understanding of how the your CSV file should be organized and what the data fields need to contain as far as 128 formatting/values go. 129 130 You can always try importing the examples/import.csv file and look at the result, assuming the values specified for the 131 membership_id in the example file match your membership level configuration. 132 133 == The .CSV file from the "Export to CSV" button on the "Members List" page won't import? == 134 135 The purpose of the resulting .CSV file from the "Export to CSV" is to generate reports that are meaningful to a human, 136 not a file that can be imported easily. This is true for any of the available Import from .CSV plugins/add-ons for 137 Paid Memberships Pro. 138 139 Basically there are a few key differences between the file resulting from the Export function and the file contents 140 needed to import the same member. 114 141 115 142 As of version 2.5, this plugin includes data checks for some of the more common mistakes I've seen in the .CSV file(s). … … 117 144 You should also check out the import example file that is linked on the "Import Members" page (under the "Choose File" button). 118 145 119 = My import fails, what is wrong? = 120 121 This is almost always related to the data in the file being imported. As a result, I've added some data tests for some of the typical mistakes I've seen in the .CSV file(s) being imported. There is also a link to an example file on the "Import Members" page (under the "Choose File" button) that illustrates a functional import file. Things lik what the field names are and the format you'll most likely need to use for the data in that column. 122 123 Check the wp-content/uploads/pmp_im_errors.log log file for details on the import operations (link should also be included in a wp-admin dashboard notice if there are errors/warnings). The log should contain suggestions on some of the more common mistakes in the data being imported. 124 125 = Do I need to include all the columns from the sample file? = 126 127 No. _Only_ include the columns where you have data to import. I.e, if none of your members need to have their membership end date defined (i.e the membership you're importing doesn't have an expiration or it's a recurring membership with a linked Payment Gateway subscription plan), just remove the column(s) you don't need. That way, the plugin doesn't try to import data that isn't there. 146 == My import fails, what is wrong? == 147 148 This is almost always related to the data in the file being imported. As a result, I've added some data tests for some 149 of the typical mistakes I've seen in the .CSV file(s) being imported. There is also a link to an example file on the 150 "Import Members" page (under the "Choose File" button) that illustrates a functional import file. Things lik what the 151 field names are and the format you'll most likely need to use for the data in that column. 152 153 Check the wp-content/uploads/pmp_im_errors.log log file for details on the import operations (link should also be 154 included in a wp-admin dashboard notice if there are errors/warnings). The log should contain suggestions on some of 155 the more common mistakes in the data being imported. 156 157 == Do I need to include all the columns from the sample file? == 158 159 No. __Only__ include the columns where you have data to import. I.e, if none of your members need to have their 160 membership end date defined (i.e the membership you're importing doesn't have an expiration or it's a recurring 161 membership with a linked Payment Gateway subscription plan), just remove the column(s) you don't need. That way, 162 the plugin doesn't try to import data that isn't there. 128 163 129 164 If a column has no data, you should remove the column and it's column header from the import file! 130 165 131 = The plugin didn't import any membership data!?! = 132 133 This is a pretty common question and the reason is almost always because there is something unexpected in the `membership_` portion of the row being imported. 134 135 Most often it's the date/time format for the membership_startdate and membership_enddate columns. 166 == The plugin didn't import any membership data!?! == 167 168 This is a pretty common question and the reason is almost always because there is something unexpected in the 169 `membership_` portion of the row being imported. 170 171 Most often it's the date/time format for the `membership_startdate` and `membership_enddate` columns. 136 172 137 173 If you use MS Excel(tm) to prepare your .CSV file, you're in for a treat... 138 174 139 In my experience, MS Excel(tm) is _really_ good at changing the date format in a spreadsheet column to whatever it thinks works best (i.e. human readable). 140 141 However, human readable is often problematic for CSV imports, so you *have to ensure* the format follows the YYYY-MM-DD HH:ii:ss (where ii = 2 digit minute value). For startdate I'd recommend using `00:00:00` and for the enddate I'd suggest using `23:59:59`. 142 143 Just to be clear: The _only_ date format for the *membership_startdate*, *membership_enddate* and the *user_registered* columns that this plugin will accept is the MySQL datetime format: YYYY-MM-DD HH:ii:ss. 175 In my experience, MS Excel(tm) is _really_ good at changing the date format in a spreadsheet column to whatever it 176 thinks works best (i.e. human readable). (If my sarcasm doesn't shine through; This actually __isn't__ a good thing!) 177 178 However, human readable is often problematic for CSV imports, so you **have to make sure** the date format follows the 179 `YYYY-MM-DD HH:ii:ss` template (where ii = 2 digit minute value). For startdate I'd recommend using `00:00:00` and 180 for the enddate I'd suggest using `23:59:59`. 181 182 Just to be clear: The __only__ date format for the `membership_startdate`, `membership_enddate` and the 183 `user_registered` columns that this plugin will accept is the MySQL datetime format: YYYY-MM-DD HH:ii:ss. 144 184 145 185 *Use anything else and your membership data will not be imported*! 146 186 147 You can change the way Microsoft Excel(tm) handles date and time data in the Regional settings, but I've yet to figure out what the ideal settings are here. Truth be told, I'm using Apple Numbers and others have had great success using Google Sheets to process and export their .CSV files. Because there are alternatives to Microsoft Excel(tm) and they seem to work a lot better for this specific task, I'm not at all inclined to spend more time on fixing something that I view to be a rather significant "bug"[1] in Excel(tm). 148 149 [1] = Being that it's an intentional usability feature, I realize Microsoft is unlikely to be all that interested in fixing this "as designed" capability they've implemented. 150 = Can this plugin be used to link sponsored members with their sponsors? = 187 You can change the way Microsoft Excel(tm) handles date and time data in the Regional settings, but I've yet to 188 figure out what the ideal settings are here. Truth be told, I'm using Apple Numbers and others have had great 189 success using Google Sheets to process and export their .CSV files. Because there are alternatives to Microsoft 190 Excel(tm) and they seem to work a lot better for this specific task, I'm not at all inclined to spend more time 191 on fixing something that I view to be a rather significant "bug"[1] in Excel(tm). 192 193 [1] = Being that it's an intentional usability feature, I realize Microsoft is unlikely to be all that interested 194 in fixing this "as designed" capability they've implemented. 195 196 == Can this plugin be used to link sponsored members with their sponsors? == 151 197 152 198 Yes. 153 199 154 In version 2.60, we added support for importing Sponsors and their sponsored members. So, if you have the PMPro Sponsored Members add-on installed, active and need to link sponsors and their sponsored members during the import with this plugin. 200 In version 2.60, we added support for importing Sponsors and their sponsored members. So, if you have the 201 PMPro Sponsored Members add-on installed, active and need to link sponsors and their sponsored members 202 during the import with this plugin. 155 203 156 204 == Importing the Sponsored user == … … 158 206 To link sponsored users with their sponsors, add the `pmprosm_sponsor` column to your import file. 159 207 160 On the data row for the _sponsored_ user, the pmprosm_sponsor column must contain the user key for the sponsor you want to link them with. 208 On the data row for the __sponsored__ user, the `pmprosm_sponsor` column must contain the user key for the sponsor 209 you want to link them with. 161 210 162 211 Or, if they don't have a sponsor, that column must be blank. 163 212 164 The sponsor key is either the email address they used when registering on your system - or the user_email column value for their user record if they're also being imported at the same time, the WordPress user ID value (numeric), or the login name used (user_login value). 213 The sponsor key is either the email address they used when registering on your system - or the user_email column 214 value for their user record if they're also being imported at the same time, the WordPress user ID value (numeric), 215 or the login name used (user_login value). 165 216 166 217 == Importing the Sponsor == 167 218 168 First of all, you will need to include a `pmprosm_seats` column as well. This column contains a numeric value to indicate the number of seats (sponsored users) this user has paid to sponsor. 219 First of all, you will need to include a `pmprosm_seats` column as well. This column contains a numeric value to 220 indicate the number of seats (sponsored users) this user has paid to sponsor. 169 221 170 222 When importing a sponsor there are a couple of scenarios; 171 223 172 1) The system already contains the sponsor code (a sponsor code is a PMPro discount code prefixed with the letter 'S') and you simply need to link the sponsor to their code. 224 1) The system already contains the sponsor code (a sponsor code is a PMPro discount code prefixed with the letter 'S') 225 and you simply need to link the sponsor to their code. 173 226 174 227 2) The system lacks the sponsor code, so you'll need one to be created. 175 228 176 For scenario 1; The sponsor code (discount code) already has a Discount Code ID (integer value, found on the PMPro "Discount Codes" settings page). This ID needs to be added in the `membership_code_id` column of the import file for the sponsor (user record), along with a numeric value in the `pmprosm_seats` column. 177 178 For scenario 2; The sponsor code is created by this plugin. It happens automatically if the sponsor user exists - or is being imported at the same time as - when the *sponsored* user is attempted imported and linked. The discount code created attempts to use the settings from the PMPro Sponsored Members add-on for the discount code. 229 For scenario 1; The sponsor code (discount code) already has a Discount Code ID (integer value, found on the PMPro 230 "Discount Codes" settings page). This ID needs to be added in the `membership_code_id` column of the import file for 231 the sponsor (user record), along with a numeric value in the `pmprosm_seats` column. 232 233 For scenario 2; The sponsor code is created by this plugin. It happens automatically if the sponsor user exists - or 234 is being imported at the same time as - when the **sponsored** user is attempted imported and linked. The discount 235 code created attempts to use the settings from the PMPro Sponsored Members add-on for the discount code. 179 236 180 237 === Caveat === … … 182 239 The order in which users are listed in the .csv import file can matter when importing sponsors and their sponsored user. 183 240 184 Although this plugin tries to re-import sponsored users if the import fails the first time, as part of the clean-up process, this retry does not guarantee success! 241 Although this plugin tries to re-import sponsored users if the import fails the first time, as part of the 242 clean-up process, this retry does not guarantee success! 185 243 186 244 As a result, it is possible that a sponsored user is imported without being linked to their sponsor. … … 198 256 As of version 2.20, we have an option to create member orders at the same time as we update the membership record. 199 257 200 That means you can now include some of the order table fields to import custom values as needed for each user/member, along with updating/adding their membership level information. 258 That means you can now include some of the order table fields to import custom values as needed for each 259 user/member, along with updating/adding their membership level information. 201 260 202 261 The supported order record columns are: … … 231 290 1. billing_phone (*) 232 291 233 All of these columns/fields should be prefixed with 'membership_'. I.e. 'membership_paypal_token' or 'membership_tax', etc. The exceptions are the 'user_id' and 'membership_id' columns/fields which should be left as 'user_id' and 'membership_id' respectively if you want to include them in the import operation(s). 234 235 The 'status' column has a limited number of valid values. By default, we recommend using either 'success' or 'cancelled' 236 237 All timestamp values ('timestamp') must use the same format as the one used by the MySQL database's 'DATETIME' format: `YYYY-MM-DD HH:MM:SS` 238 239 *PLEASE NOTE:* 240 241 Although you _can_ specify an account number (accountnumber) in the import file, doing that will *not* result in this plugin importing and activating subscriptions or payments by credit card. 242 243 You CANNOT use this tool to import and *create* subscription plans, or transactions, on the payment gateway for your Paid Memberships Pro users. 244 245 Including anything other than a masked Credit Card number for the "membership_accountnumber" column *is a really bad idea*[1]! 246 247 A masked credit card number = Only the last 4 digits are real and the rest are repetitions of the 'X' character (XXXXXXXXXXXX1234). 248 249 [1] = Importing a full credit card number will exponentially increase the probability that you, in the event of a security problem on your site, will have to pay the Payment Card Industry (PCI) massive fines. Simply put; Don't import Credit Card information! Instead, ask your members to resubmit their information when the site is back online/live. 250 251 *This plugin does NOT mask your credit card numbers for you!* 252 253 = Supported membership_gateway options = 254 255 The Import Members from CSV plugin supports specifying different payment gateways for the user record(s) when importing order data (i.e. the "Attempt to create PMPro Order record" option has been selected). At present, the payment gateways that can be specified in the `membership_gateway` column are: 292 All of these columns/fields should be prefixed with `membership_`. I.e. `membership_paypal_token` or `membership_tax`, 293 etc. The exceptions are the `user_id` and `membership_id` columns/fields which should be left as `user_id` and 294 `membership_id` respectively if you want to include them in the import operation(s). 295 296 The `status` column has a limited number of valid values. By default, we recommend using either `success` or `cancelled` 297 298 All timestamp values ('timestamp') must use the same format as the one used by the MySQL database's 'DATETIME' 299 format: `YYYY-MM-DD HH:MM:SS` 300 301 **PLEASE NOTE:** 302 303 Although you _can_ specify an account number (`accountnumber`) in the import file, doing that will *not* result in 304 this plugin importing and activating subscriptions or payments by credit card. 305 306 You CANNOT use this tool to import and **create** subscription plans, or transactions, on the payment gateway for 307 your Paid Memberships Pro users. 308 309 Including anything other than a masked Credit Card number for the `membership_accountnumber` column *is a really 310 bad idea*[1]! 311 312 A masked credit card number = Only the last 4 digits are real and the rest are repetitions of the 'X' 313 character (`XXXXXXXXXXXX1234`). 314 315 [1] = Importing a full credit card number will exponentially increase the probability that you, in the event of a 316 security problem on your site, will have to pay the Payment Card Industry (PCI) massive fines. Simply put; Don't import 317 Credit Card information! Instead, ask your members to resubmit their information when the site is back online/live. 318 319 **This plugin does NOT mask your credit card numbers for you!** 320 321 == Supported membership_gateway options == 322 323 The Import Members from CSV plugin supports specifying different payment gateways for the user record(s) when 324 importing order data (i.e. the "Attempt to create PMPro Order record" option has been selected). At present, the 325 payment gateways that can be specified in the `membership_gateway` column are: 256 326 257 327 1. authorizenet 258 1. braintree 259 1. check 260 1. cybersource 261 1. payflowpro 262 1. paypal 263 1. paypalexpress 264 1. paypalstandard 265 1. stripe 266 1. twocheckout 267 268 During the import operation, the plugin will verify that the specified payment gateway integration is one of the supported payment gateway integrations for Paid Memberships Pro. 269 270 Specifying a Payment Gateway Integration that has not been configured for use during the PMPro checkout process would render the order record invalid. 271 272 NOTE: The limitations to how Paid Memberships Pro supports/handles multiple payment gateway integrations at the same time still apply. 273 274 = Adding billing address information to the PMPro Order import = 275 276 The normal way to import billing address data to the database for a member/user is to use the `pmpro_b[*]` fields (pmpro_bfirstname, pmpro_blastname, pmpro_baddress1, pmpro_baddress2, pmpro_bcity, pmpro_bstate, pmpro_bzipcode, pmpro_bcountry and pmpro_bphone). 277 278 If the pmpro_b* field data is present in the row and the 'Add order' option is selected for the import file, the import will attempt to populate the order billing information using the pmpro_b* data. 328 2. braintree 329 3. check 330 4. cybersource 331 5. payflowpro 332 6. paypal 333 7. paypalexpress 334 8. paypalstandard 335 9. stripe 336 10. twocheckout 337 11. payfast 338 339 During the import operation, the plugin will verify that the specified payment gateway integration is one of the 340 supported payment gateway integrations for Paid Memberships Pro. 341 342 Specifying a Payment Gateway Integration that has not been configured for use during the PMPro checkout process would 343 render the order record invalid. 344 345 **NOTE:** The limitations to how Paid Memberships Pro supports/handles multiple payment gateway integrations at the 346 same time still apply. 347 348 == Adding billing address information to the PMPro Order import == 349 350 The normal way to import billing address data to the database for a member/user is to use the `pmpro_b[*]` fields 351 (`pmpro_bfirstname`, `pmpro_blastname`, `pmpro_baddress1`, `pmpro_baddress2`, `pmpro_bcity`, `pmpro_bstate`, 352 `pmpro_bzipcode`, `pmpro_bcountry` and `pmpro_bphone`). 353 354 If the `pmpro_b*` field data is present in the row and the 'Add order' option is selected for the import file, the 355 import will attempt to populate the order billing information using the `pmpro_b*` data. 279 356 280 357 = How should the .csv file be defined? = … … 287 364 288 365 For example; 289 To have a 2 column .csv file, each row **after** the header row, the row should look something like this: `"my first column data","my second \"escaped\" column data"`. 290 291 The application you use to edit and export your .CSV file will need to be configured appropriately before you export the .csv file. 366 To have a 2 column .csv file, each row **after** the header row, the row should look something like this: 367 `"my first column data","my second \"escaped\" column data"`. 368 369 The application you use to edit and export your .CSV file will need to be configured appropriately before you 370 export the .csv file. 292 371 293 372 = Why am I or my users not receiving New user notifications = 294 373 295 There are a couple of possible reasons, as far as I can tell. The functionality in WordPress that generates the "new user notification" message is what they call "pluggable". That means that it's possible for a plugin (any plugin!) to override the behavior of the functionality. So the first thing I'd suggest investigating is whether you have a pluing active that intentionally changes/modifies/updates how the `wp_new_user_notification()` function works/behaves. 296 297 Next, it's (very) possible that your hosting environment doesn't want you to be sending out a lot of email messages from their servers. As a result, the import operation could potentially trip their anti-spam measures and blocking you from sending any messages. 298 299 Third, the recipient email server may be using a SBL (Spam Black List) and have your web server IP listed as a typical source of Spam messages (it happens, a lot). 300 301 = I've set the 'membership_status' column to 'inactive', but the user's imported membership level is currently 'active'? = 374 There are a couple of possible reasons, as far as I can tell. The functionality in WordPress that generates the 375 "new user notification" message is what they call "pluggable". That means that it's possible for a plugin (any plugin!) 376 to override the behavior of the functionality. So the first thing I'd suggest investigating is whether you have a 377 plugin active that intentionally changes/modifies/updates how the `wp_new_user_notification()` function works/behaves. 378 379 Next, it's (very) possible that your hosting environment doesn't want you to be sending out a lot of email messages 380 from their servers. As a result, the import operation could potentially trip their anti-spam measures and blocking 381 you from sending any messages. 382 383 Third, the recipient email server may be using a SBL (Spam Black List) and have your web server IP listed as a 384 typical source of Spam messages (it happens, a lot). 385 386 == I've set the 'membership_status' column to 'inactive', but the user's imported membership level is currently 'active'? == 302 387 303 388 This is due to what I'd term a bug in Paid Memberships Pro. This issue doesn't currently have a fix. 304 389 305 Basically, the 'inactive' status will only apply to the order record (if it's created, see above) and *not* to the user's membership status. 306 307 NOTE: Assigning a membership level for a user will cause them to be given an active membership on the site when the import operation is complete, regardless of the value supplied for the 'membership_status' column. 308 309 = How do I import an existing payment plan (recurring billing plan) for a user? = 390 Basically, the 'inactive' status will only apply to the order record (if it's created, see above) and *not* to the 391 user's membership status. 392 393 **NOTE:** Assigning a membership level for a user will cause them to be given an active membership on the site when 394 the import operation is complete, regardless of the value supplied for the 'membership_status' column. 395 396 == How do I import an existing payment plan (recurring billing plan) for a user? == 310 397 311 398 This only works if the plan already exists on the payment gateway itself. 312 399 313 There is no way to use this plugin to import a new member/user and have the system create a recurring billing plan for them. 314 315 = Can I use this plugin to create new billing plans or trigger charges on the payment gateway for an imported user? = 400 There is no way to use this plugin to import a new member/user and have the system create a recurring billing plan 401 for them. 402 403 == Can I use this plugin to create new billing plans or trigger charges on the payment gateway for an imported user? == 316 404 317 405 No. 318 406 319 = What are the constraints for WordPress Multisite import operations?=407 == What are the constraints for WordPress Multisite import operations? == 320 408 321 409 As documented by Paid Memberships Pro, the PMPro plugin cannot be Network Activated. 322 410 323 This import plugin will work from the site(s) where PMPro is active _and_ have the same membership level IDs identified as are listed in the `membership_id` column of the import file you're using. 324 325 If your primary site has a configured and active Paid Memberships Pro installation, you could theoretically start the plugin from the Network Admin dashboard (which will send you to the primary site anyway). 326 327 The users being imported will only be linked to the site you import them to. Their membership data will only be visible on the PMPro site(s) that have the membership level ID(s) configured that match those in the import file. 411 This import plugin will work from the site(s) where PMPro is active _and_ have the same membership level IDs 412 identified as are listed in the `membership_id` column of the import file you're using. 413 414 If your primary site has a configured and active Paid Memberships Pro installation, you could theoretically start 415 the plugin from the Network Admin dashboard (which will send you to the primary site anyway). 416 417 The users being imported will only be linked to the site you import them to. Their membership data will only be 418 visible on the PMPro site(s) that have the membership level ID(s) configured that match those in the import file. 328 419 329 420 = Welcome Email Message (imported_welcome.html template) issues = … … 332 423 please make sure the 'membership_status' field is included in the import .csv file and contains the `active` value. 333 424 334 As a design philosophy, we treat an inactive member as somebody who should _not_ receive welcome messages (you may disagree..?) 335 336 = What GDPR impacted data is stored by this plugin? = 337 338 Obviously, there's the user data that this plugin is designed to import. This plugin does _not_ track, report, or allow download/deletion of any data it imports. There are (now or soon) other plugin options to handle those requirements from the GDPR legislation. 339 340 In an attempt to make the "Donation" button less intrusive, we attempt to track the computer (IP) address when somebody clicks the button. This plugin does _not_ link the IP address to a user account, so it should be a little more challenging to identify the person who clicked the "Donate" button for any 3rd party who gets access to your database than simply looking at the options saved by this plugin. 341 342 The IP tracking information (the IP address) is stored in the WordPress options table (`wp_options`) using the `e20r_import_has_donated` option name. That option can safely be deleted in the database if you do not wish to have IPs tracked. Deleting the option from the database will obviously re-enable the Donation nag. 343 344 As long as this plugin remains installed and active on the server, the tracked IP address will automatically be removed from the option 2 months after the admin clicked the Donation button. 425 As a design philosophy, we treat an inactive member as somebody who should _not_ receive welcome messages 426 (you may disagree..?) 427 428 == What GDPR impacted data is stored by this plugin? == 429 430 Obviously, there's the user data that this plugin is designed to import. This plugin does _not_ track, report, or 431 allow download/deletion of any data it imports. There are (now or soon) other plugin options to handle those 432 requirements from the GDPR legislation. 433 434 In an attempt to make the "Donation" button less intrusive, we attempt to track the computer (IP) address when 435 somebody clicks the button. This plugin does _not_ link the IP address to a user account, so it should be a little 436 more challenging to identify the person who clicked the "Donate" button for any 3rd party who gets access to your 437 database than simply looking at the options saved by this plugin. 438 439 The IP tracking information (the IP address) is stored in the WordPress options table (`wp_options`) using the 440 `e20r_import_has_donated` option name. That option can safely be deleted in the database if you do not wish to have 441 IPs tracked. Deleting the option from the database will obviously re-enable the Donation nag. 442 443 As long as this plugin remains installed and active on the server, the tracked IP address will automatically be 444 removed from the option 2 months after the admin clicked the Donation button. 345 445 346 446 The option is removed when the plugin is deactivated in the "Plugins" admin panel. 347 447 348 Nag tracking can be disabled altogether with the `e20r_import_donation_tracking_disabled` filter: `add_filter( 'e20r_import_donation_tracking_disabled', '__return_true' );'` 448 Nag tracking can be disabled altogether with the `e20r_import_donation_tracking_disabled` filter: 449 `add_filter( 'e20r_import_donation_tracking_disabled', '__return_true' );'` 349 450 350 451 == Installation == 351 452 352 453 1. Upload the `pmpro-import-members-from-csv` folder to the `/wp-content/plugins/` directory. 353 1. Activate the plugin through the 'Plugins' menu in WordPress.454 2. Activate the plugin through the 'Plugins' menu in WordPress. 354 455 355 456 == Screenshots == 356 457 357 458 1. User import screen 358 1. Ongoing (background) import screen359 1. Default settings on the user import screen459 2. Ongoing (background) import screen 460 3. Default settings on the user import screen 360 461 361 462 == Known Issues == … … 369 470 == Supported Filters and Actions == 370 471 371 The list of filters and actions supported by this plugin can be found in the [Filters](./docs/FILTERS.md) and [Actions](./docs/ACTIONS.md) documentation. 472 The list of filters and actions supported by this plugin can be found in the [Filters](./docs/FILTERS.md) and 473 [Actions](./docs/ACTIONS.md) documentation. -
pmpro-import-members-from-csv/tags/v3.0.6/class.pmpro-import-members.php
r2555218 r2563515 1 <?php 1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName 2 2 /** 3 3 Plugin Name: Import Paid Memberships Pro Members from CSV 4 4 Plugin URI: http://wordpress.org/plugins/pmpro-import-members-from-csv/ 5 5 Description: Import Users and their metadata from a csv file. 6 Version: 3.0. 46 Version: 3.0.6 7 7 Requires PHP: 7.3 8 8 Author: <a href="https://eighty20results.com/thomas-sjolshagen/">Thomas Sjolshagen <[email protected]></a> … … 42 42 use function plugin_dir_path; 43 43 use function add_action; 44 use function error_log; 44 use function error_log; // phpcs:ignore 45 45 46 46 if ( ! defined( 'E20R_IM_CSV_DELIMITER' ) ) { … … 55 55 56 56 if ( ! defined( 'E20R_IMPORT_VERSION' ) ) { 57 define( 'E20R_IMPORT_VERSION', '3.0. 4' );58 } 59 60 require_once plugin_dir_path( __FILE__ ) . ' /ActivateUtilitiesPlugin.php';57 define( 'E20R_IMPORT_VERSION', '3.0.6' ); 58 } 59 60 require_once plugin_dir_path( __FILE__ ) . 'class-activateutilitiesplugin.php'; 61 61 62 62 /** … … 107 107 foreach ( $base_paths as $base_path ) { 108 108 109 $iterator = new RecursiveDirectoryIterator( 110 $base_path, 111 RecursiveDirectoryIterator::SKIP_DOTS | 112 RecursiveIteratorIterator::SELF_FIRST | 113 RecursiveIteratorIterator::CATCH_GET_CHILD | 114 RecursiveDirectoryIterator::FOLLOW_SYMLINKS 115 ); 116 117 $filter = new RecursiveCallbackFilterIterator( 118 $iterator, 119 function ( $current, $key, $iterator ) use ( $filename ) { 120 121 // Skip hidden files and directories. 122 if ( $current->getFilename()[0] === '.' || $current->getFilename() === '..' ) { 123 return false; 109 try { 110 $iterator = new RecursiveDirectoryIterator( 111 $base_path, 112 RecursiveDirectoryIterator::SKIP_DOTS | 113 RecursiveIteratorIterator::SELF_FIRST | 114 RecursiveIteratorIterator::CATCH_GET_CHILD | 115 RecursiveDirectoryIterator::FOLLOW_SYMLINKS 116 ); 117 } catch ( \Exception $e ) { 118 print 'Error: ' . $e->getMessage(); // phpcs:ignore 119 return; 120 } 121 122 try { 123 $filter = new RecursiveCallbackFilterIterator( 124 $iterator, 125 function ( $current, $key, $iterator ) use ( $filename ) { 126 127 // Skip hidden files and directories. 128 if ( '.' === $current->getFilename()[0] || '..' === $current->getFilename() ) { 129 return false; 130 } 131 132 if ( $current->isDir() ) { 133 // Only recurse into intended subdirectories. 134 return $current->getFilename() === $filename; 135 } else { 136 // Only consume files of interest. 137 return str_starts_with( $current->getFilename(), $filename ); 138 } 124 139 } 125 126 if ( $current->isDir() ) { 127 // Only recurse into intended subdirectories. 128 return $current->getFilename() === $filename; 129 } else { 130 // Only consume files of interest. 131 return str_starts_with( $current->getFilename(), $filename ); 132 } 133 } 134 ); 140 ); 141 } catch ( \Exception $e ) { 142 echo 'Autoloader error: ' . $e->getMessage(); // phpcs:ignore 143 return; 144 } 135 145 136 146 foreach ( new RecursiveIteratorIterator( $iterator ) as $f_filename => $f_file ) { -
pmpro-import-members-from-csv/tags/v3.0.6/docker-compose.yml
r2554806 r2563515 19 19 ports: 20 20 - ${WP_PORT}:80 21 stdin_open: true # docker run -i 22 tty: true # docker run -t 21 23 command: 22 24 - /bin/sh … … 57 59 MYSQL_RANDOM_ROOT_PASSWORD: ${MYSQL_RANDOM_ROOT_PASSWORD} 58 60 volumes: 59 - ${LOCAL_PLUGIN_DIR} :/docker-entrypoint-initdb.d61 - ${LOCAL_PLUGIN_DIR}/tests/_data:/docker-entrypoint-initdb.d -
pmpro-import-members-from-csv/tags/v3.0.6/javascript/pmpro-import-members-from-csv.js
r2554806 r2563515 1 1 /** 2 * Copyright (c) 2018 -2019- Eighty / 20 Results by Wicked Strong Chicks.2 * Copyright (c) 2018 - 2021 - Eighty / 20 Results by Wicked Strong Chicks. 3 3 * ALL RIGHTS RESERVED 4 4 * -
pmpro-import-members-from-csv/tags/v3.0.6/src/class-data.php
r2554806 r2563515 82 82 // Add PMPro info as applicable 83 83 if ( ! empty( $user ) ) { 84 // @phpstan-ignore-next-line 84 85 $user->membership_level = ( 85 86 function_exists( 'pmpro_getMembershipLevelForUser' ) ? … … 88 89 ); 89 90 91 // @phpstan-ignore-next-line 90 92 $user->membership_levels = ( 91 93 function_exists( 'pmpro_getMembershipLevelsForUser' ) ? … … 332 334 333 335 if ( ! in_array( $billing_field_name, array_keys( $billing_fields ), true ) ) { 334 return null;336 return false; 335 337 } 336 338 -
pmpro-import-members-from-csv/tags/v3.0.6/src/class-email-templates.php
r2554806 r2563515 76 76 77 77 // Email 'your membership account is active' to member if they were imported with an active member status 78 if ( true === (bool) $send_email && 79 isset( $fields['membership_status'] ) && 'active' === $fields['membership_status'] && 80 1 === version_compare( PMPRO_VERSION, '1.9.5' ) 78 if ( 79 true === (bool) $send_email && 80 isset( $fields['membership_status'] ) && 'active' === $fields['membership_status'] && 81 // @phpstan-ignore-next-line 82 1 === version_compare( PMPRO_VERSION, '1.9.5' ) 81 83 ) { 82 84 $subject = null; … … 103 105 $this->error_log->debug( "Using {$template_name} template for '{$subject}' message" ); 104 106 107 // PMPro is not good at defining properties in classes (badly reliant on the historically dynamic nature of PHP) 108 // so will have PHPStan ignore these lines until PMPro cleans up their stuff 109 // (i.e. TODO when PMPro takes better advantage of PHP) 105 110 $email = new \PMProEmail(); 106 $email->email = $user->user_email; 107 $email->data = apply_filters( 'pmp_im_imported_member_message_data', array() ); 108 $email->subject = $subject; 109 $email->template = $template_name; 111 $email->email = $user->user_email; // @phpstan-ignore-line 112 $email->data = apply_filters( 'pmp_im_imported_member_message_data', array() ); // @phpstan-ignore-line 113 $email->subject = $subject; // @phpstan-ignore-line 114 $email->template = $template_name; // @phpstan-ignore-line 110 115 111 116 if ( ! empty( $body ) ) { 112 $email->body = $body; 117 $email->body = $body; // @phpstan-ignore-line 113 118 } else { 114 $email->body = $this->load_email_body( null, $email->template ); 119 $email->body = $this->load_email_body( null, $email->template ); // @phpstan-ignore-line 115 120 } 116 121 117 122 $email->body = apply_filters( 'pmp_im_imported_member_message_body', $email->body ); 123 $email->body = apply_filters( 'e20r_import_member_message_body', $email->body ); 118 124 119 125 // Process and send email … … 228 234 foreach ( $locations as $path ) { 229 235 if ( true === file_exists( $path ) ) { 230 $body = file_get_contents( $path ); 236 $body = file_get_contents( $path ); // phpcs:ignore 231 237 break; 232 238 } … … 265 271 'subject' => __( 'Welcome to my new website', 'pmpro-import-members-from-csv' ), 266 272 'description' => __( 'Import: Welcome Member', 'pmpro-import-members-from-csv' ), 273 // phpcs:ignore 267 274 'body' => file_get_contents( Import_Members::$plugin_path . '/emails/imported_member.html' ), 268 275 ); -
pmpro-import-members-from-csv/tags/v3.0.6/src/class-error-log.php
r2554806 r2563515 67 67 'error' 68 68 ); 69 69 return; 70 70 } 71 71 … … 146 146 * Identify the calling function (used in debug logger 147 147 * 148 * @return array|string148 * @return string 149 149 * 150 150 * @access public 151 151 */ 152 private function who_called_me() {152 private function who_called_me() : string { 153 153 $trace = debug_backtrace(); // phpcs:ignore 154 154 $caller = $trace[2]; -
pmpro-import-members-from-csv/tags/v3.0.6/src/class-import-members.php
r2554946 r2563515 144 144 145 145 if ( false === apply_filters( 'e20r_utilities_module_installed', false ) ) { 146 add_action( 'init', '\E20R\Import\Loader::is_utilities_module_active', 10 );147 } 148 add_action( 'plugins_loaded', array( Email_Templates::get_instance(), 'load_hooks' ), 99 );149 add_action( 'plugins_loaded', array( Ajax::get_instance(), 'load_hooks' ), 99 );150 add_action( 'plugins_loaded', array( Page::get_instance(), 'load_hooks' ), 99 );146 add_action( 'init', '\E20R\Import\Loader::is_utilities_module_active', 10, 0 ); 147 } 148 add_action( 'plugins_loaded', array( Email_Templates::get_instance(), 'load_hooks' ), 99, 0 ); 149 add_action( 'plugins_loaded', array( Ajax::get_instance(), 'load_hooks' ), 99, 0 ); 150 add_action( 'plugins_loaded', array( Page::get_instance(), 'load_hooks' ), 99, 0 ); 151 151 152 152 // Add validation logic for all modules 153 add_action( 'plugins_loaded', array( User_Validation::get_instance(), 'load_actions' ), 30 );154 add_action( 'plugins_loaded', array( PMPro_Validation::get_instance(), 'load_actions' ), 31 );155 add_action( 'plugins_loaded', array( BuddyPress_Validation::get_instance(), 'load_actions' ), 32 );156 157 add_action( 'init', array( $this, 'load_i18n' ), 5 );158 add_action( 'init', array( $this->data, 'process_csv' ) );159 160 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );161 162 // PMPro specific import functionality163 // phpcs:ignore -We do this in the CSV() class as it's a clean-up operation164 // add_action( 'e20r_before_user_import', array( $this->csv, 'pre_import' ), 10, 2 ); 153 add_action( 'plugins_loaded', array( User_Validation::get_instance(), 'load_actions' ), 30, 0 ); 154 add_action( 'plugins_loaded', array( PMPro_Validation::get_instance(), 'load_actions' ), 31, 0 ); 155 add_action( 'plugins_loaded', array( BuddyPress_Validation::get_instance(), 'load_actions' ), 32, 0 ); 156 157 add_action( 'init', array( $this, 'load_i18n' ), 5, 0 ); 158 add_action( 'init', array( $this->data, 'process_csv' ), 10, 0 ); 159 160 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 10, 0 ); 161 162 // PMPro specific capabilities 163 // We do this in the CSV() class as it's a clean-up operation 164 // add_action( 'e20r_before_user_import', array( $this->csv, 'pre_import' ), 10, 2 ); // phpcs:ignore 165 165 add_filter( 'e20r_import_usermeta', array( $this->import_user, 'import_usermeta' ), 10, 2 ); 166 166 add_action( … … 179 179 180 180 // Clear action handler(s) from the Import Users from CSV Integration Add-on for PMPro 181 add_action( 'wp_loaded', array( $this, 'remove_iucsv_support' ), 10 );181 add_action( 'wp_loaded', array( $this, 'remove_iucsv_support' ), 10, 0 ); 182 182 183 183 // Remove Import action for Sponsored Members add-on (handled directly by this plugin) 184 184 remove_action( 'is_iu_post_user_import', 'pmprosm_is_iu_post_user_import', 20 ); 185 185 186 if ( class_exists( 'E20R\Utilities\Licensing\Licensing' ) ) { 187 $licensing = new Licensing( self::E20R_LICENSE_SKU ); 188 189 if ( $licensing->is_licensed( self::E20R_LICENSE_SKU, false ) ) { 190 do_action( 'e20r_import_load_licensed_modules' ); 191 } 186 if ( ! class_exists( 'E20R\Utilities\Licensing\Licensing' ) ) { 187 return; 188 } 189 190 $check = new \ReflectionMethod( 'E20R\Utilities\Licensing\Licensing', '__construct' ); 191 192 if ( false === $check->isPrivate() ) { 193 $licensing = new Licensing( self::E20R_LICENSE_SKU ); 194 $is_licensed = $licensing->is_licensed( self::E20R_LICENSE_SKU, false ); 195 } else { 196 // @phpstan-ignore-next-line 197 $is_licensed = Licensing::is_licensed( self::E20R_LICENSE_SKU, false ); 198 } 199 200 if ( true === $is_licensed ) { 201 do_action( 'e20r_import_load_licensed_modules' ); 192 202 } 193 203 } … … 249 259 */ 250 260 $max_run_time = ( 251 apply_filters( 'pmp_im_import_time_per_record', 3) *252 apply_filters( ' pmp_im_import_records_per_scan', $this->variables->get( 'per_partial' ) )261 $this->variables->calculate_per_record_time() * 262 apply_filters( 'e20r_import_records_per_scan', $this->variables->get( 'per_partial' ) ) 253 263 ); 254 264 … … 261 271 'pmpro-import-members-from-csv', 262 272 plugins_url( 'css/pmpro-import-members-from-csv.css', E20R_IMPORT_PLUGIN_FILE ), 263 null,273 array(), 264 274 E20R_IMPORT_VERSION 265 275 ); 276 266 277 // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NotInFooter 267 278 wp_register_script( … … 358 369 public function plugin_row_meta( $links, $file ) { 359 370 360 if ( true === stripos( $file, 'class.pmpro-import-members.php' ) ) {371 if ( false !== stripos( $file, 'class.pmpro-import-members.php' ) ) { 361 372 // Add (new) 'Import Users from CSV' links to plugin listing 362 373 $new_links = array( -
pmpro-import-members-from-csv/tags/v3.0.6/src/class-variables.php
r2554806 r2563515 302 302 $this->error_log->debug( "File name from transient is {$this->filename} vs tmp name of {$tmp_name}" ); 303 303 304 if ( empty( $ filename ) && ( ! empty( $tmp_name ) && file_exists( $tmp_name ) ) ) {304 if ( empty( $this->filename ) && ( ! empty( $tmp_name ) && file_exists( $tmp_name ) ) ) { 305 305 306 306 $this->error_log->debug( "Update/move the {$tmp_name} file!" ); … … 312 312 exit(); 313 313 } 314 } elseif ( ! empty( $filename ) ) {315 $this->filename = $filename;316 314 } 317 315 … … 345 343 346 344 if ( ! empty( $max_exec_time ) && ( is_numeric( $per_record_time ) ) ) { 347 $this->per_partial = round( ceil( $max_exec_time / (float) $per_record_time ), 0);345 $this->per_partial = intval( round( ceil( $max_exec_time / (float) $per_record_time ), 0 ) ); 348 346 } 349 347 -
pmpro-import-members-from-csv/tags/v3.0.6/src/import/class-ajax.php
r2554946 r2563515 119 119 $this->error_log->debug( "Visitor ({$client_ip}) clicked the 'Donate' button" ); 120 120 wp_send_json_success(); 121 exit();122 121 } 123 122 } 124 123 125 124 wp_send_json_error(); 126 exit();127 125 } 128 126 … … 162 160 if ( false === $this->delete_file( $logfile_path ) ) { 163 161 wp_send_json_error(); 164 exit();165 162 } 166 163 167 164 // Return success 168 165 wp_send_json_success(); 169 exit();170 166 } 171 167 … … 186 182 $this->error_log->debug( 'File not found/not available. Nothing to clean!' ); 187 183 wp_send_json_success(); 188 exit();189 184 } 190 185 … … 197 192 198 193 wp_send_json_error(); 199 exit();200 194 } 201 195 … … 208 202 209 203 wp_send_json_success(); 210 exit();211 204 } 212 205 … … 244 237 $this->error_log->debug( 'Nonce verified in import_members_from_csv()' ); 245 238 246 /* 239 /* @codingStandardsIgnoreStart 240 * 247 241 if ( false === wp_verify_nonce( $_REQUEST['e20r-im-import-members-wpnonce'], 'e20r-im-import-members' ) ) { 248 242 249 243 $msg = __( 'Insecure connection attempted!', 'pmpro-import-members-from-csv' ); 250 244 251 wp_send_json_error( array( 'status' => - 1, 252 'message' => $msg, 253 ) ); 254 exit(); 255 } 256 */ 245 wp_send_json_error( 246 array( 247 'status' => - 1, 248 'message' => $msg, 249 ) 250 ); 251 } 252 * @codingStandardsIgnoreEnd 253 */ 257 254 258 255 // Get our settings … … 268 265 ) 269 266 ); 270 exit();271 267 } 272 268 … … 287 283 ) 288 284 ); 289 exit();290 285 } 291 286 … … 371 366 } 372 367 373 $buffered_text = ob_get_clean(); 368 $buffered_text = ob_get_clean(); 369 $display_errors = $this->variables->get( 'display_errors' ); 374 370 375 371 // No users imported (or done) … … 383 379 //Clear position 384 380 delete_option( "e20rcsv_{$file}" ); 385 $display_errors = $this->variables->get( 'display_errors' );386 381 387 382 // Delete the transient storing the file name … … 397 392 ) 398 393 ); 399 exit();400 394 401 395 } elseif ( ! empty( $results['errors'] ) ) { … … 425 419 ) 426 420 ); 427 exit();428 421 } else { 429 422 … … 462 455 ) 463 456 ); 464 exit();465 457 } 466 458 } -
pmpro-import-members-from-csv/tags/v3.0.6/src/import/class-csv.php
r2554806 r2563515 21 21 22 22 use E20R\Import_Members\Error_Log; 23 use E20R\Import_Members\Modules\Users\Column_Validation as User_Validation;24 23 use E20R\Import_Members\Modules\Users\Import_User; 25 24 use E20R\Import_Members\Status; … … 37 36 38 37 /** 39 * The CSV file (as a SplFileObject() class )40 *41 * @var SplFileObject $file_object42 */43 private $file_object;44 45 /**46 38 * Error log class 47 39 * @var Error_Log|null $error_log = null; … … 60 52 * @var null|CSV $csv 61 53 */ 62 private $csv = null;54 private $csv; 63 55 64 56 /** … … 201 193 } 202 194 195 // @phpstan-ignore-next-line 196 $this->error_log->debug( 'Directory error? ' . ( $directory_error ? 'Yes' : 'No' ) ); 197 $this->error_log->debug( 'File upload not selected error? ' . ( $no_file_error ? 'Yes' : 'No' ) ); 198 $this->error_log->debug( 'File limit error? ' . ( $clean_file_error ? 'Yes' : 'No' ) ); 199 200 // @phpstan-ignore-next-line 203 201 if ( ( true === $no_file_error || true === $directory_error || true === $clean_file_error ) ) { 204 205 202 $this->error_log->debug( 'Error: Problem with uploaded file...' ); 206 $this->error_log->debug( 'Directory error? ' . ( $directory_error ? 'Yes' : 'No' ) );207 $this->error_log->debug( 'File upload not selected error? ' . ( $no_file_error ? 'Yes' : 'No' ) );208 $this->error_log->debug( 'File limit error? ' . ( $clean_file_error ? 'Yes' : 'No' ) );209 210 203 return false; 211 204 } … … 333 326 334 327 // Mac CR+LF fix 335 ini_set( 'auto_detect_line_endings', true);328 ini_set( 'auto_detect_line_endings', '1' ); 336 329 337 330 $file = basename( $file_name ); … … 414 407 415 408 $this->error_log->debug( "Processing next user data. (previous line #: {$active_line_number})" ); 416 417 409 $this->extract_data( 418 410 $line, … … 493 485 $user_id = $import_user->import( $user_data, $user_meta, $headers ); 494 486 495 if ( false ===$user_ids ) {487 if ( ! $user_ids ) { 496 488 497 489 $msg = sprintf( … … 519 511 // Close the file (done by the destructor for the SplFileObject() class) 520 512 $file_object = null; 521 ini_set( 'auto_detect_line_endings', true);513 ini_set( 'auto_detect_line_endings', '1' ); 522 514 523 515 // One more thing to do after all imports? -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/BuddyPress/class-buddypress.php
r2554806 r2563515 72 72 * @access private 73 73 */ 74 p rivatefunction __construct() {74 public function __construct() { 75 75 $this->data = new Data(); 76 76 $this->error_log = new Error_Log(); // phpcs:ignore … … 84 84 ); 85 85 } 86 87 /**88 * Get or instantiate and return this class (BuddyPress)89 *90 * @return BuddyPress|null91 */92 // public static function get_instance() {93 // if ( null === self::$instance ) {94 // self::$instance = new self();95 // }96 // return self::$instance;97 // }98 86 99 87 /** … … 149 137 return $field_list + $this->field_list; 150 138 } 151 152 /**153 * Clone the class (Singleton)154 *155 * @access private156 */157 private function __clone() {158 // TODO: Implement __clone() method.159 }160 139 } -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/BuddyPress/class-column-validation.php
r2554806 r2563515 38 38 namespace E20R\Import_Members\Modules\BuddyPress; 39 39 40 41 40 use E20R\Import_Members\Error_Log; 42 41 use E20R\Import_Members\Validate\Base_Validation; 42 use E20R\Import_Members\Modules\BuddyPress\BuddyPress; 43 43 44 44 class Column_Validation extends Base_Validation { 45 45 46 46 /** 47 47 * Get or instantiate and get the current class 48 48 * 49 * @return Column_Validation| null49 * @return Column_Validation|Base_Validation|null 50 50 */ 51 51 public static function get_instance() { … … 53 53 if ( true === is_null( self::$instance ) ) { 54 54 self::$instance = new self(); 55 55 56 56 add_filter( 57 57 'e20r_import_errors_to_ignore', 58 58 array( self::$instance, 'load_ignored_module_errors' ), 59 59 10, 60 260 2 61 61 ); 62 62 63 63 // Add list of errors to ignore for the BuddyPress module 64 64 self::$instance->errors_to_ignore = apply_filters( … … 71 71 return self::$instance; 72 72 } 73 73 74 74 /** 75 75 * Define the module specific errors to ignore … … 81 81 */ 82 82 public function load_ignored_module_errors( $ignored_error_list, $module_name = 'buddypress' ) { 83 84 if ( $module_name !== 'buddypress') {83 84 if ( 'buddypress' !== $module_name ) { 85 85 return $ignored_error_list; 86 86 } 87 88 $this->error_log->debug( "Loading BuddyPress specific error(s) when it's safe to can continue importing");89 87 88 $this->error_log->debug( "Loading BuddyPress specific error(s) when it's safe to can continue importing" ); 89 90 90 $this->errors_to_ignore = array( 91 91 'bp_field_name' => true, 92 92 ); 93 93 94 94 return $ignored_error_list + $this->errors_to_ignore; 95 95 } 96 96 97 97 /** 98 98 * Load action and filter handlers for PMPro validation … … 103 103 return; 104 104 } 105 105 106 106 add_filter( 'e20r_import_members_validate_field_data', array( $this, 'bp_field_exists' ), 1, 3 ); 107 107 } … … 117 117 */ 118 118 public function bp_field_exists( $has_error, $user_id, $fields ) { 119 120 $buddy_press = BuddyPress::get_instance();119 120 $buddy_press = new BuddyPress(); 121 121 $buddy_press->load_fields( array() ); 122 122 123 if ( ! isset( $fields['bp_field_name'] )) {124 $this->error_log->debug( "No need to process 'bp_field_name' column");123 if ( ! isset( $fields['bp_field_name'] ) ) { 124 $this->error_log->debug( "No need to process 'bp_field_name' column" ); 125 125 return $has_error; 126 126 } 127 127 128 if ( ! isset( $fields['bp_field_name'] ) && in_array( 'bp_field_name', array_keys( $fields ) ) ) {128 if ( ! isset( $fields['bp_field_name'] ) && in_array( 'bp_field_name', array_keys( $fields ), true ) ) { 129 129 $this->error_log->debug( "'bp_field_name' is doesn't need to be processed..." ); 130 130 return $has_error; … … 132 132 133 133 if ( isset( $fields['bp_field_name'] ) && empty( $fields['bp_field_name'] ) ) { 134 $has_error = $has_error && ( true &&! $this->ignore_validation_error( 'bp_field_name' ) );134 $has_error = $has_error && ( ! $this->ignore_validation_error( 'bp_field_name' ) ); 135 135 } 136 136 137 137 // FIXME: Add check for 'bp_field_exists' for the supplied fields/data 138 138 139 139 return $has_error; 140 140 } 141 142 /**143 * Disable the __clone() magic method144 *145 * @access private146 */147 private function __clone() {148 // TODO: Implement __clone() method.149 }150 141 } -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/BuddyPress/class-import-buddypress.php
r2554806 r2563515 20 20 namespace E20R\Import_Members\Modules\BuddyPress; 21 21 22 23 22 class Import_BuddyPress { 24 23 // TODO: Create BuddyPress import class 25 24 } -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/PMPro/class-column-validation.php
r2554806 r2563515 32 32 * Instance of the PMPro Column_Validation class 33 33 * 34 * @var null|Column_Validation $instance34 * @var null|Column_Validation|Base_Validation $instance 35 35 */ 36 36 protected static $instance = null; … … 39 39 * Get or instantiate and get the current class 40 40 * 41 * @return Column_Validation| null42 */ 43 public static function get_instance() : \E20R\Import_Members\Modules\PMPro\Column_Validation{41 * @return Column_Validation|Base_Validation|null 42 */ 43 public static function get_instance() { 44 44 45 45 if ( true === is_null( self::$instance ) ) { … … 165 165 $e20r_import_err['invalid_membership_id'] = new WP_Error( 'e20r_im_member', $msg ); 166 166 167 $has_error = true &&( ! $this->ignore_validation_error( 'invalid_membership_id' ) );167 $has_error = ( ! $this->ignore_validation_error( 'invalid_membership_id' ) ); 168 168 169 169 return $has_error; … … 173 173 * Can't import membership data when user has incorrect start date format 174 174 * 175 * @param $has_error176 * @param $user_id177 * @param $fields175 * @param bool $has_error 176 * @param int $user_id 177 * @param array $fields 178 178 * 179 179 * @return bool … … 228 228 ); 229 229 230 $has_error = true &&( ! $this->ignore_validation_error( 'startdate_format' ) );230 $has_error = ( ! $this->ignore_validation_error( 'startdate_format' ) ); 231 231 } 232 232 … … 237 237 * Can't import membership data when user has incorrect start date format or value 238 238 * 239 * @param $has_error240 * @param $user_id241 * @param $fields239 * @param bool $has_error 240 * @param int $user_id 241 * @param array $fields 242 242 * 243 243 * @return bool … … 289 289 290 290 $e20r_import_err['no_startdate'] = new WP_Error( 'e20r_im_member', $msg ); 291 $has_error = true &&( ! $this->ignore_validation_error( 'no_startdate' ) );291 $has_error = ( ! $this->ignore_validation_error( 'no_startdate' ) ); 292 292 } 293 293 return $has_error; … … 297 297 * Possible problem for membership data when user has incorrect end date format or value 298 298 * 299 * @param $has_error300 * @param $user_id301 * @param $fields299 * @param bool $has_error 300 * @param int $user_id 301 * @param array $fields 302 302 * 303 303 * @return bool … … 335 335 336 336 $e20r_import_err['bad_format_enddate'] = new WP_Error( 'e20r_im_member', $msg ); 337 $has_error = true &&( ! $this->ignore_validation_error( 'bad_format_enddate' ) );337 $has_error = ( ! $this->ignore_validation_error( 'bad_format_enddate' ) ); 338 338 339 339 $should_be = Time::convert( $fields['membership_enddate'] ); … … 378 378 if ( 379 379 ! empty( $fields['membership_enddate'] ) && 380 isset( $fields['membership_status'] ) && 'inactive' === $fields['membership_status'] && 380 ! empty( $fields['membership_status'] ) && 381 'inactive' === $fields['membership_status'] && 381 382 ( time() < strtotime( $fields['membership_enddate'], time() ) ) 382 383 ) { … … 395 396 396 397 $e20r_import_err['inactive_and_enddate'] = new WP_Error( 'e20r_im_member', $msg ); 397 $has_error = true &&( ! $this->ignore_validation_error( 'inactive_and_enddate' ) );398 $has_error = ( ! $this->ignore_validation_error( 'inactive_and_enddate' ) ); 398 399 } 399 400 … … 450 451 451 452 $e20r_import_err['valid_status'] = new WP_Error( 'e20r_im_member', $msg ); 452 $has_error = true &&( ! $this->ignore_validation_error( 'valid_status' ) );453 $has_error = ( ! $this->ignore_validation_error( 'valid_status' ) ); 453 454 } 454 455 … … 505 506 506 507 $e20r_import_err['link_subscription'] = new WP_Error( 'e20r_im_member', $msg ); 507 $has_error = true &&( ! $this->ignore_validation_error( 'link_subscription' ) );508 $has_error = ( ! $this->ignore_validation_error( 'link_subscription' ) ); 508 509 } 509 510 … … 552 553 553 554 $e20r_import_err['invalid_recurring_config'] = new WP_Error( 'e20r_im_member', $msg ); 554 $has_error = true &&( ! $this->ignore_validation_error( 'invalid_recurring_config' ) );555 $has_error = ( ! $this->ignore_validation_error( 'invalid_recurring_config' ) ); 555 556 } 556 557 … … 594 595 ); 595 596 $e20r_import_err['sub_id_no_paym_id'] = new WP_Error( 'e20r_im_member', $msg ); 597 $has_error = ( ! $this->ignore_validation_error( 'sub_id_no_paym_id' ) ); 596 598 } 597 599 … … 674 676 $e20r_import_err[ "no_membership_id_column_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 675 677 676 $has_error = true &&( ! $this->ignore_validation_error( 'no_membership_id_column' ) );678 $has_error = ( ! $this->ignore_validation_error( 'no_membership_id_column' ) ); 677 679 } 678 680 … … 690 692 $e20r_import_err[ "no_membership_id_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 691 693 692 $has_error = true &&( ! $this->ignore_validation_error( 'no_membership_id' ) );694 $has_error = ( ! $this->ignore_validation_error( 'no_membership_id' ) ); 693 695 } 694 696 … … 707 709 $e20r_import_err[ "cancelling_membership_level_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 708 710 709 $has_error = false;711 $has_error = ( ! $this->ignore_validation_error( 'cancelling_membership_level' ) ); 710 712 } 711 713 … … 752 754 $e20r_import_err[ "level_exists_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 753 755 754 $has_error = true &&( ! $this->ignore_validation_error( 'level_exists' ) );756 $has_error = ( ! $this->ignore_validation_error( 'level_exists' ) ); 755 757 } 756 758 return $has_error; … … 799 801 $e20r_import_err[ "recurring_w_enddate_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 800 802 801 $has_error = true &&( ! $this->ignore_validation_error( 'recurring_w_enddate' ) );803 $has_error = ( ! $this->ignore_validation_error( 'recurring_w_enddate' ) ); 802 804 } 803 805 return $has_error; … … 845 847 $e20r_import_err[ "correct_gw_env_variable_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 846 848 847 $has_error = true &&( ! $this->ignore_validation_error( 'correct_gw_env_variable' ) );849 $has_error = ( ! $this->ignore_validation_error( 'correct_gw_env_variable' ) ); 848 850 } 849 851 … … 893 895 $e20r_import_err[ "supported_gateway_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 894 896 895 $has_error = true &&( ! $this->ignore_validation_error( 'supported_gateway' ) );897 $has_error = ( ! $this->ignore_validation_error( 'supported_gateway' ) ); 896 898 } 897 899 } -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/PMPro/class-import-member.php
r2554806 r2563515 176 176 $has_error = false; 177 177 $membership_in_the_past = false; 178 179 // Define table names 180 $pmpro_member_table = "{$wpdb->prefix}pmpro_memberships_users"; 181 $pmpro_dc_table = "{$wpdb->prefix}pmpro_discount_codes"; 182 183 $current_blog_id = get_current_blog_id(); 178 $current_blog_id = get_current_blog_id(); 184 179 185 180 $this->error_log->debug( "Current blog ID: {$current_blog_id}" ); … … 266 261 $wpdb->prepare( 267 262 "SELECT dc.id 268 FROM {$ pmpro_dc_table}AS dc263 FROM {$wpdb->prefix}pmpro_discount_codes AS dc 269 264 WHERE dc.code = %s 270 265 LIMIT 1", … … 291 286 // Update all currently active memberships with the specified ID for the specified user 292 287 $updated = $wpdb->update( 293 $pmpro_member_table,288 "{$wpdb->prefix}pmpro_memberships_users", 294 289 array( 'status' => 'admin_cancelled' ), 295 290 array( … … 392 387 $wpdb->prepare( 393 388 "SELECT mt.id 394 FROM {$ pmpro_member_table}AS mt389 FROM {$wpdb->prefix}pmpro_memberships_users AS mt 395 390 WHERE mt.user_id = %d AND mt.membership_id = %d AND mt.status = %s 396 391 ORDER BY mt.id DESC LIMIT 1", … … 404 399 $wpdb->prepare( 405 400 "SELECT mt.id 406 FROM {$ pmpro_member_table}AS mt401 FROM {$wpdb->prefix}pmpro_memberships_users AS mt 407 402 WHERE mt.user_id = %d AND mt.membership_id = %d 408 403 ORDER BY mt.id DESC LIMIT 1", … … 430 425 431 426 if ( false !== $wpdb->update( 432 $pmpro_member_table,427 "{$wpdb->prefix}pmpro_memberships_users", 433 428 array( 434 429 'status' => 'inactive', … … 469 464 470 465 if ( false === $wpdb->update( 471 $pmpro_member_table,466 "{$wpdb->prefix}pmpro_memberships_users", 472 467 array( 473 468 'status' => 'active', … … 515 510 516 511 // Update the error status 517 if ( true === $has_error ) { 518 update_option( 'e20r_import_errors', $has_error ); 519 } 512 update_option( 'e20r_import_errors', $has_error ); 520 513 521 514 if ( is_multisite() ) { … … 592 585 } 593 586 594 $order = new \MemberOrder(); 595 $order->user_id = $user_id; 596 $order->membership_id = isset( $record['membership_id'] ) ?? $record['membership_id']; 597 $order->InitialPayment = ! empty( $record['membership_initial_payment'] ) ? $record['membership_initial_payment'] : null; 587 $order = new \MemberOrder(); 588 $order->user_id = $user_id; // @phpstan-ignore-line 589 $order->membership_id = isset( $record['membership_id'] ) ?? $record['membership_id']; // @phpstan-ignore-line 590 591 // phpcs:ignore 592 $order->InitialPayment = ! empty( $record['membership_initial_payment'] ) ? $record['membership_initial_payment'] : null; // @phpstan-ignore-line 598 593 599 594 /** … … 616 611 617 612 if ( ! isset( $order->billing ) ) { 618 $order->billing = new \stdClass(); 613 $order->billing = new \stdClass(); // @phpstan-ignore-line 619 614 } 620 615 … … 635 630 if ( 'total' === $field_name && ! empty( $record['membership_initial_payment'] ) ) { 636 631 637 $order->total = $record['membership_initial_payment']; 632 $order->total = $record['membership_initial_payment']; // @phpstan-ignore-line 638 633 639 634 } elseif ( 'total' === $field_name && ( … … 642 637 ) ) { 643 638 644 $order->total = $record['membership_billing_amount']; 639 $order->total = $record['membership_billing_amount']; // @phpstan-ignore-line 645 640 646 641 } elseif ( 'total' !== $field_name ) { 647 642 648 643 if ( 'status' === $field_name ) { 644 // @phpstan-ignore-next-line 649 645 $order->{$field_name} = ( isset( $record[ $full_field_name ] ) && 'active' === $record[ $full_field_name ] ? 'success' : 'cancelled' ); 650 646 } else { … … 663 659 664 660 if ( isset( $record['membership_gateway_environment'] ) && strtolower( $default_environment ) !== strtolower( $record['membership_gateway_environment'] ) ) { 665 $order->gateway_environment = strtolower( $record['membership_gateway_environment'] ); 661 $order->gateway_environment = strtolower( $record['membership_gateway_environment'] ); // @phpstan-ignore-line 666 662 } 667 663 668 664 if ( true === $membership_in_the_past ) { 669 $order->status = 'cancelled'; 665 $order->status = 'cancelled'; // @phpstan-ignore-line 670 666 } 671 667 -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/PMPro/class-import-sponsors.php
r2554806 r2563515 74 74 */ 75 75 public function load_sponsor_import() { 76 if ( true === Licensing::is_licensed( 'import_sponsors' ) ) { 76 $check = new \ReflectionMethod( 'E20R\Utilities\Licensing\Licensing', '__construct' ); 77 78 if ( false === $check->isPrivate() ) { 79 $licensing = new Licensing( Import_Members::E20R_LICENSE_SKU ); 80 $is_licensed = $licensing->is_licensed( Import_Members::E20R_LICENSE_SKU, false ); 81 } else { 82 // @phpstan-ignore-next-line 83 $is_licensed = Licensing::is_licensed( Import_Members::E20R_LICENSE_SKU, false ); 84 } 85 86 if ( true === $is_licensed ) { 77 87 add_action( 'e20r_after_user_import', array( $this, 'maybe_add_sponsor_info' ), 100, 3 ); 78 88 } … … 169 179 * 170 180 * @param int $sponsored_user_id 171 * @param Sponsor $sponsor181 * @param Sponsor|\WP_User $sponsor 172 182 * @param bool $last_try 173 183 * … … 196 206 197 207 // Get user info and ensure they have a current membership level 198 $sponsored_user = get_userdata( $sponsored_user_id ); 208 $sponsored_user = get_userdata( $sponsored_user_id ); 209 210 // @phpstan-ignore-next-line 199 211 $sponsored_user->membership_level = pmpro_getMembershipLevelForUser( $sponsored_user_id, true ); 200 212 $delayed_sponsor_link = $this->variables->get( 'delayed_sponsor_link' ); … … 235 247 236 248 //Make sure the sponsor has a discount code 237 $code_id = pmprosm_getCodeByUserID( $sponsor_id ); 249 $code_id = pmprosm_getCodeByUserID( $sponsor_id ); // @phpstan-ignore-line 238 250 239 251 $this->error_log->debug( "Got sponsor code {$code_id} for sponsor {$sponsor_id}" ); … … 295 307 $this->error_log->debug( "Have to create a sponsor code for {$sponsor_id}" ); 296 308 309 // @phpstan-ignore-next-line 297 310 $code_id = pmprosm_createSponsorCode( $sponsor_id, $sponsor_level_id, $uses ); 298 311 } … … 317 330 'code_id' => $code_id, 318 331 'user_id' => $sponsored_user_id, 319 'membership_id' => $sponsored_user->membership_level->id, 332 'membership_id' => $sponsored_user->membership_level->id, // @phpstan-ignore-line 320 333 'status' => 'active', 321 334 ); … … 342 355 $this->error_log->debug( "Updated member record for {$sponsored_user_id} with sponsor info" ); 343 356 357 // @phpstan-ignore-next-line 344 358 pmprosm_addDiscountCodeUse( $sponsored_user_id, $sponsored_user->membership_level->ID, $code_id ); 345 359 346 360 $this->error_log->debug( "Updated the usage of {$code_id}" ); 347 361 348 if ( empty( $e rror ) ) {362 if ( empty( $e20r_import_err ) ) { 349 363 $status = true; 350 364 … … 353 367 354 368 } else { 355 $ error->log_errors(356 array( $error ),369 $this->error_log->log_errors( 370 $e20r_import_err, 357 371 $this->variables->get( 'log_file_path' ), 358 372 $this->variables->get( 'log_file_url' ) … … 398 412 } 399 413 414 // @phpstan-ignore-next-line 400 415 $sponsor->membership_level = pmpro_getMembershipLevelForUser( $sponsor_id, true ); 401 416 -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/PMPro/class-pmpro.php
r2554806 r2563515 18 18 */ 19 19 namespace E20R\Import_Members\Modules\PMPro; 20 21 20 22 21 use E20R\Import_Members\Error_Log; -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/PMPro/class-sponsor.php
r2554806 r2563515 20 20 namespace E20R\Import_Members\Modules\PMPro; 21 21 22 23 22 use E20R\Import_Members\Data; 24 23 25 24 class Sponsor { 26 25 27 26 /** 28 27 * The sponsor's WP_User ID … … 31 30 */ 32 31 private $ID = null; 33 32 34 33 /** 35 34 * User Record for the sponsor … … 38 37 */ 39 38 private $user = null; 40 39 41 40 /** 42 41 * The membership level information for the sponsor … … 45 44 */ 46 45 private $membership_level = null; 47 46 48 47 /** 49 48 * Sponsor constructor. 50 49 * 51 * @param $user_id50 * @param int|string $user_id 52 51 * 53 52 * @throws \Exception 54 53 */ 55 54 public function __construct( $user_id = null ) { 56 57 $data = Data::get_instance();58 55 56 $data = new Data(); 57 59 58 if ( ! empty( $user_id ) ) { 60 59 $this->user = $data->get_user_info( $user_id ); 61 60 } 62 63 if ( !empty( $user_id ) && empty( $this->user ) ) { 64 throw new \Exception( sprintf( __( 'No user with that ID (%s) found!', 'pmpro-import-members-from-csv' ), $user_id ) ); 61 62 if ( ! empty( $user_id ) && empty( $this->user ) ) { 63 throw new \Exception( 64 sprintf( 65 // translators: %s - Supplied User ID, email or login name 66 __( 'No user with that ID (%s) found!', 'pmpro-import-members-from-csv' ), 67 $user_id 68 ) 69 ); 65 70 } 66 71 } 67 72 68 73 /** 69 74 * Set Sponsor parameter by type … … 76 81 */ 77 82 public function set( $param, $value, $type = null ) { 78 83 79 84 $attributes = get_class_vars( __CLASS__ ); 80 81 if ( ! in_array( $param, $attributes ) && ! in_array( $type, $attributes) ) {85 86 if ( ! in_array( $param, $attributes, true ) && ! in_array( $type, $attributes, true ) ) { 82 87 return false; 83 88 } 84 89 85 90 switch ( $type ) { 86 91 87 92 case 'user': 88 93 if ( isset( $this->user->{$param} ) ) { … … 92 97 } 93 98 break; 94 99 95 100 case 'membership': 96 97 101 if ( isset( $this->membership_level->{$param} ) ) { 98 102 $this->membership_level->{$param} = $value; … … 101 105 } 102 106 break; 103 107 104 108 default: 105 109 $this->{$param} = $value; 106 110 } 107 111 108 112 return true; 109 113 } 110 114 111 115 /** 112 116 * Return the type specific parameter (membership info, user info, class variable) 113 117 * 114 * @param string $type118 * @param string|null $type 115 119 * @param string $param 116 120 * … … 118 122 */ 119 123 public function get( $type, $param ) { 120 124 121 125 $attributes = get_class_vars( __CLASS__ ); 122 126 $value = null; 123 124 if ( ! in_array( $param, $attributes ) ) {127 128 if ( ! in_array( $param, $attributes, true ) ) { 125 129 return false; 126 130 } 127 131 128 132 switch ( $type ) { 129 133 130 134 case 'user': 131 135 $value = $this->user->{$param}; 132 136 break; 133 137 134 138 case 'membership': 135 136 139 $value = $this->membership_level->{$param}; 137 140 break; 138 141 139 142 default: 140 143 $value = $this->{$param}; 141 144 } 142 145 143 146 return $value; 144 147 } -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/Users/class-column-validation.php
r2554806 r2563515 36 36 * Get or instantiate and get the current class 37 37 * 38 * @return Column_Validation| null38 * @return Column_Validation|Base_Validation|null 39 39 */ 40 40 public static function get_instance() { … … 134 134 * @param null|string|string[] $field_name 135 135 * 136 * @return bool|int |false136 * @return bool|int 137 137 */ 138 138 public function validate_user_id( $has_error, $user_id, $record, $field_name = null ) { … … 147 147 $this->error_log->debug( 'Cannot find one of the expected column(s): ID, user_email, user_login' ); 148 148 return $has_error; 149 }150 151 if ( is_array( $field_name ) ) {152 // TODO: Process list of fields153 149 } 154 150 … … 190 186 return true; 191 187 } 192 193 /**194 * Disable the __clone() magic method195 *196 * @access private197 */198 private function __clone() {199 // TODO: Implement __clone() method.200 }201 188 } -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/Users/class-import-user.php
r2554806 r2563515 353 353 } else { 354 354 $update = false; 355 $id = null; 355 356 // Here we're supposed to hash the password 356 357 // $user_pass = wp_hash_password( $userdata['user_pass'] ); … … 555 556 556 557 if ( true === $update ) { 557 $wpdb->update( $wpdb->users, $data, compact( ' ID' ) );558 $wpdb->update( $wpdb->users, $data, compact( 'id' ) ); 558 559 $user_id = (int) $id; 559 560 } else { -
pmpro-import-members-from-csv/tags/v3.0.6/src/modules/Users/class-user-validation.php
r2554806 r2563515 20 20 namespace E20R\Import_Members\Validate; 21 21 22 23 22 use E20R\Import_Members\Import_Members; 24 23 use E20R\Import_Members\Status; 25 24 26 25 class User_Validation extends Validate { 27 28 26 27 /** 28 * Return the User_Validation class instance 29 * 30 * @return Base_Validation|User_Validation|null 31 */ 32 public static function get_instance() { 33 if ( null === self::$instance ) { 34 self::$instance = new self(); 35 } 36 37 return self::$instance; 38 } 39 40 /** 41 * Return list of validation errors we'll ignore (only warn for) 42 * 43 * @param array $ignored_error_list 44 * @param string $module_name 45 * 46 * @return array 47 */ 48 public function load_ignored_module_errors( $ignored_error_list, $module_name = 'users' ) { 49 return $ignored_error_list; 50 } 51 52 /** 53 * Load action and filter handlers for PMPro validation 54 */ 55 public function load_actions() { 56 57 add_filter( 58 'e20r_import_users_validate_field_data', 59 array( $this, 'validate' ), 60 1, 61 3 62 ); 63 } 64 29 65 /** 30 66 * Process the status for user validations and set a status message … … 36 72 */ 37 73 public static function status_msg( $status, $allow_update ) { 38 74 39 75 global $e20r_import_err; 40 76 global $active_line_number; 41 77 42 78 $should_exit = false; 43 79 … … 51 87 52 88 case Status::E20R_ERROR_UPDATE_NEEDED_NOT_ALLOWED: 53 $msg = __(89 $msg = __( 54 90 'User ID specified and user record exists but the "Update User Record" option is not selected', 55 91 'pmpro-import-members-from-csv' … … 67 103 break; 68 104 default: 69 70 $msg = null; 105 $msg = null; 71 106 $should_exit = false; 72 107 } 73 108 74 109 // Process the resulting error/warning message 75 110 if ( ! empty( $msg ) ) { 76 111 77 112 // Save the error message (based on the supplied status) 78 $e20r_import_err[ "user_check_{$active_line_number}"] = $msg;79 113 $e20r_import_err[ "user_check_{$active_line_number}" ] = $msg; 114 80 115 return $should_exit; 81 116 } 82 117 83 118 return false; 84 119 } 85 120 86 121 /** 87 122 * Validate the User information in the record … … 93 128 */ 94 129 public static function validate( $record, $allow_update ) { 95 96 return false; 130 131 // TODO: Implement validation logic for User record(s) 132 return ! empty( $record ); 97 133 } 98 134 } -
pmpro-import-members-from-csv/tags/v3.0.6/src/validate/class-base-validation.php
r2554806 r2563515 23 23 24 24 use E20R\Import_Members\Error_Log; 25 use E20R\Import_Members\Modules\PMPro\Column_Validation as PMPro_Validation; 26 use E20R\Import_Members\Modules\Users\Column_Validation as User_Validation; 27 use E20R\Import_Members\Modules\BuddyPress\Column_Validation as BP_Validation; 25 28 26 29 abstract class Base_Validation { … … 29 32 * Instance of the column validation logic for PMPro 30 33 * 31 * @var null|Base_Validation 34 * @var null|Base_Validation|PMPro_Validation|User_Validation|BP_Validation 32 35 */ 33 36 protected static $instance = null; … … 75 78 * Get or instantiate and get the current class 76 79 * 77 * @return Column_Validation|Base_Validation|null80 * @return User_Validation|PMPro_Validation|BP_Validation|Base_Validation|null 78 81 */ 79 82 abstract public static function get_instance(); … … 81 84 /** 82 85 * Load all validation actions for the specific module 83 *84 * @return null85 86 */ 86 87 abstract public function load_actions(); -
pmpro-import-members-from-csv/tags/v3.0.6/src/validate/class-date-format.php
r2554806 r2563515 21 21 22 22 class Date_Format { 23 23 24 24 /** 25 25 * Test the date supplied for MySQL compliance … … 33 33 */ 34 34 public static function validate( $date, $format ) { 35 35 36 36 $check_date = \DateTime::createFromFormat( $format, $date ); 37 $retval = ( false !== $check_date ) && ( $check_date->format( $format ) == $date ); 38 39 return $retval; 37 38 return ( false !== $check_date ) && ( $check_date->format( $format ) === $date ); 40 39 } 41 40 42 41 } -
pmpro-import-members-from-csv/trunk/CHANGELOG.md
r2555218 r2563515 6 6 7 7 ## [Unreleased] 8 9 ## v3.0.6 - 2021-07-13 10 - BUG FIX: Updates to presence check for test types (Thomas Sjolshagen) 11 - BUG FIX: Didn't install the ruleset when in GitHub Action (Thomas Sjolshagen) 12 - BUG FIX: Fatal error during install of production composer dependencies (Thomas Sjolshagen) 13 - BUG FIX: acceptance-test target didn't work (Thomas Sjolshagen) 14 - BUG FIX: TTYs in docker-compose.yml (Thomas Sjolshagen) 15 - BUG FIX: Adding a stripped down data file for the WP Unit tests (Thomas Sjolshagen) 16 - BUG FIX: Refactor of the Makefile (Thomas Sjolshagen) 17 - BUG FIX: Didn't exclude inc/ in codeception.dist.yml (Thomas Sjolshagen) 18 - BUG FIX: Handle DB Dump if present (Thomas Sjolshagen) 19 - BUG FIX: Reverted inclusion of SQL file in repo (Thomas Sjolshagen) 20 - BUG FIX: Wrong path to the DB file we need for testing (Thomas Sjolshagen) 21 - BUG FIX: Add Docker Hub login to release-plugin.yml (Thomas Sjolshagen) 22 - BUG FIX: Include SQL so it can be used by WP Unit ++ tests (Thomas Sjolshagen) 23 - BUG FIX: Fix issue with TTY during GitHub action execution (Thomas Sjolshagen) 24 - BUG FIX: Adding COMPOSE_INTERACTIVE_NO_CLI=1 to work around 'The input device is not a TTY' errors/warnings (Thomas Sjolshagen) 25 - BUG FIX: Make sure we use the correct Docker Hub login approach (Thomas Sjolshagen) 26 - BUG FIX: Use log file if it's available (Thomas Sjolshagen) 27 - BUG FIX: Use action recipe for docker hub login (Thomas Sjolshagen) 28 - BUG FIX: More testing of docker hub login (Thomas Sjolshagen) 29 - BUG FIX: Split remote and local removal of tags (Thomas Sjolshagen) 30 - BUG FIX: Updates to debug Docker Hub login issues (Thomas Sjolshagen) 31 - BUG FIX: Make sure the file check works w/o error as a GitHub action (Thomas Sjolshagen) 32 - BUG FIX: Revert the shell based check for phpcs presence (shouldn't be needed) (Thomas Sjolshagen) 33 - BUG FIX: Troubleshooting the Makefile (Thomas Sjolshagen) 34 - BUG FIX: Use BASH by default when running commands (Thomas Sjolshagen) 35 - BUG FIX: Clean up PHONY targets and enable curl output (Thomas Sjolshagen) 36 - BUG FIX: Add PHPStan testing (Thomas Sjolshagen) 37 - BUG FIX: Enable parallel execution for PHPStan and omit a couple of error types (Thomas Sjolshagen) 38 - BUG FIX: PHPStan fixes to handle different versions of the Licensing module (Thomas Sjolshagen) 39 - BUG FIX: PHPStan related fixes in the Users class-column-validation.php file (Thomas Sjolshagen) 40 - BUG FIX: PHPStan related fixes in class-import-sponsors.php (Thomas Sjolshagen) 41 - BUG FIX: Incomplete argument type definition for Sponsor::get() method (Thomas Sjolshagen) 42 - BUG FIX: PHPStan related fixes in the PMPro class-import-member.php file (Thomas Sjolshagen) 43 - BUG FIX: Various logic and PHPStan related fixes in the PMPro class-column-validation.php file (Thomas Sjolshagen) 44 - BUG FIX: Various PHPStan related fixes in the BuddyPress class-column-validation.php file (Thomas Sjolshagen) 45 - BUG FIX: Various PHPStan related fixes for class-csv.php (Thomas Sjolshagen) 46 - BUG FIX: Remove unneeded exit() calls - PHPStan fixes for class-ajax.php (Thomas Sjolshagen) 47 - BUG FIX: Incorrect PHPStan errors for add_filter() function (Thomas Sjolshagen) 48 - BUG FIX: The $id parameter wasn't defined for all code paths in class-import-user.php (Thomas Sjolshagen) 49 - BUG FIX: Fixed PMPro related ignore/revert ignore comments in class-email-templates.php (Thomas Sjolshagen) 50 - BUG FIX: Ignored a PHPStan non-error in class-data.php (Thomas Sjolshagen) 51 - BUG FIX: Return value in PHPDoc wrong for load_actions() method (Thomas Sjolshagen) 52 - BUG FIX: PHPStan fixes for class-base-validation.php (Thomas Sjolshagen) 53 - BUG FIX: PHPStan fixes for class-activateutilitiesplugin.php (Thomas Sjolshagen) 54 - BUG FIX: Fatal errors due to poor error recovery in autoloader (Thomas Sjolshagen) 55 - BUG FIX: Clean up config for phpstan-test target (Thomas Sjolshagen) 56 - BUG FIX: code-standards-test target depends on plugin and composer modules (Thomas Sjolshagen) 57 - BUG FIX: Add WP Neutron code standards config (Thomas Sjolshagen) 58 - BUG FIX: PHPCS ignored some of the plugin source files (Thomas Sjolshagen) 59 - BUG FIX: Add WP Neutron code standards config (Thomas Sjolshagen) 60 - BUG FIX: Code sniffer updates for Buddypress version of class-column-validation.php (Thomas Sjolshagen) 61 - BUG FIX: Code sniffer updates for class-buddypress.php (Thomas Sjolshagen) 62 - BUG FIX: Code sniffer updates for class-import-buddypress.php (Thomas Sjolshagen) 63 - BUG FIX: Code sniffer updates for class-import-member.php (Thomas Sjolshagen) 64 - BUG FIX: Code sniffer updates for class-pmpro.php (Thomas Sjolshagen) 65 - BUG FIX: Code sniffer updates for class-ajax.php (Thomas Sjolshagen) 66 - BUG FIX: Code sniffer updates for class-column-validation.php (Thomas Sjolshagen) 67 - BUG FIX: Include the ActivateUtilitiesPlugin class path and clean up paths to scan/include (Thomas Sjolshagen) 68 - BUG FIX: PHPStan test execution settings (Thomas Sjolshagen) 69 - BUG FIX: Didn't autoload classes we expected to load (Thomas Sjolshagen) 70 - BUG FIX: PHPStan test command updated, making sure the inc/wp_plugins dir exists, and more info for some of the testing tagets (Thomas Sjolshagen) 71 - BUG FIX: php-composer target didn't work and phpstan memory limit set to 'unlimited' (Thomas Sjølshagen) 72 - BUG FIX: Renamed deps to wp-deps (Thomas Sjolshagen) 73 - BUG FIX: per_partial is an integer and not a float (Thomas Sjolshagen) 74 - BUG FIX: PHPStan test doesn't need a docker container to run (Thomas Sjolshagen) 75 - BUG FIX: PHPStan errors we don't care about (PMPro functions / class members, etc) (Thomas Sjolshagen) 76 - BUG FIX: PHPStan errors we don't care about (Thomas Sjolshagen) 77 - BUG FIX: PHPDoc string was incorrect (Thomas Sjolshagen) 78 - BUG FIX: Fatal error because we attempted to use Data::get_instance() plus PHPCS nits (Thomas Sjolshagen) 79 - BUG FIX: PHPStan complained about require_once call for Utility loader (Thomas Sjolshagen) 80 - BUG FIX: Make config more dynamic for testing (Thomas Sjolshagen) 81 - BUG FIX: Fix config for PHPStan testing (Thomas Sjolshagen) 82 - BUG FIX: Updates in support of PHPStan testing (Thomas Sjolshagen) 83 - BUG FIX: User Validation class was only partially implemented (Thomas Sjolshagen) 84 - BUG FIX: Wrong file name for plugin file (Thomas Sjolshagen) 85 - BUG FIX: Re-inverted the DOWNLOAD logic (Thomas Sjolshagen) 86 - BUG FIX: Use the get_plugin_version.sh script (Thomas Sjolshagen) 87 - BUG FIX: Made the wrong assumption about the location of the Version string (Thomas Sjolshagen) 88 - BUG FIX: Clean up build vs download for E20R plugins (Thomas Sjolshagen) 89 - BUG FIX: Refactored utility module build process (Thomas Sjolshagen) 90 - BUG FIX: Refactored build target (Thomas Sjolshagen) 91 - BUG FIX: More errors when determining local presence for Utilities (Thomas Sjolshagen) 92 - BUG FIX: Annoying errors in the Makefile (including -z vs -n issues) (Thomas Sjolshagen) 93 - BUG FIX: Build target updates to be .php file change triggered (Thomas Sjolshagen) 94 - BUG FIX: Wrong build target for custom E20R modules (Thomas Sjolshagen) 95 - BUG FIX: Utilities module dependency build fixes (Thomas Sjolshagen) 96 - BUG FIX: Didn't handle when Utilities module is in local git repo (Thomas Sjolshagen) 97 98 ## v3.0.5 - 2021-07-05 99 - BUG FIX: Reformatted README.md (Thomas Sjolshagen) 100 - BUG FIX: Duplicate entries in CHANGELOG.md (Thomas Sjolshagen) 101 - BUG FIX: Using template for metadata.json (Thomas Sjolshagen) 102 - BUG FIX: Build script for readme files updated (Thomas Sjolshagen) 103 - BUG FIX: Typo and formatting updates (Thomas Sjolshagen) 104 - BUG FIX: Don't clean up E20R custom plugins unless in one of the clean-up targets (Thomas Sjolshagen) 105 - BUG FIX: Unit tests do not require WordPress (Thomas Sjolshagen) 106 - BUG FIX: Wrong path for database container volume (Thomas Sjolshagen) 107 - BUG FIX: Typo in comments (Thomas Sjolshagen) 108 - BUG FIX: Old file name for plugin activation of 00-e20r-utilities (Thomas Sjolshagen) 109 - BUG FIX: Missing class definition for assertEquals() call in class-csv-UnitTest.php and class-import-members-UnitTest.php (Thomas Sjolshagen) 110 - BUG FIX: Errors when building the 00-e20r-utilities plugin as a dependency and add clean-up target (Thomas Sjolshagen) 111 - BUG FIX: Simplify config of make/build scripts (Thomas Sjolshagen) 112 - BUG FIX: Potentially inconsistent port use in test environment (Thomas Sjolshagen) 113 - BUG FIX: Initial commit - extracts version info for plugin (Thomas Sjolshagen) 114 - BUG FIX: Shift to PHPUnit 8.x (from 9.x) (Thomas Sjolshagen) 115 - BUG FIX: Use local repo to build 00-e20r-utilities plugin when possible (Thomas Sjolshagen) 116 - BUG FIX: Fixed the WP Unit test suite config for Codeception testing (Thomas Sjolshagen) 117 - BUG FIX: Pasted the wrong path to the Docker key file (Thomas Sjolshagen) 118 - BUG FIX: Be explicit about priorities and args when loading filter/action hooks (Thomas Sjolshagen) 119 - BUG FIX: Setting to handle WP's multi-site testing (Thomas Sjolshagen) 120 - BUG FIX: Use configurable vendor directory for composer (Thomas Sjolshagen) 121 - BUG FIX: Didn't account for the different possibilities for the Utilities/Licensing module (Thomas Sjolshagen) 122 - BUG FIX: A bit too aggressive when clearing inc/ directory (Thomas Sjolshagen) 123 - BUG FIX: Use custom gitignore file for inc/ directory (Thomas Sjolshagen) 124 - BUG FIX: Change log script fixed to avoid duplicate entries, blank line errors, etc (Thomas Sjolshagen) 125 - BUG FIX: Fixed the messed up autoloader and coding standard errors (Thomas Sjolshagen) 126 - BUG FIX: Removed unneeded variables in Makefile (Thomas Sjolshagen) 127 - BUG FIX: Refactored Makefile to be a bit more generic (Thomas Sjolshagen) 128 - BUG FIX: Update data file location for manual testing (Thomas Sjolshagen) 129 - BUG FIX: Renamed ActivateUtilitiesPlugin.php to fix coding standards errors (Thomas Sjolshagen) 130 - BUG FIX: Fix Coding Standard errors in class.pmpro-import-members.php (Thomas Sjolshagen) 131 - BUG FIX: Fix Coding Standard errors in class-validate.php (Thomas Sjolshagen) 132 - BUG FIX: Fix Coding Standard errors in class-date-format.php (Thomas Sjolshagen) 133 - BUG FIX: Fix Coding Standard problems (Thomas Sjolshagen) 134 - BUG FIX: Handle exporting the plugin as a git archive (Thomas Sjolshagen) 135 - BUG FIX: Calculated the wrong timeout value for the JS based background import (Thomas Sjolshagen) 136 - BUG FIX: Updated copyright notice (Thomas Sjolshagen) 137 - BUG FIX: PHPCS was a bit too inclusive (Thomas Sjolshagen) 138 - BUG FIX: Include the README.md file (Thomas Sjolshagen) 139 - BUG FIX: Relocate build status badge (Thomas Sjolshagen) 140 - BUG FIX: Splitting log/doc/updater json generation further (Thomas Sjolshagen) 141 - BUG FIX: Updated CHANGELOG (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 142 - BUG FIX: Error generating documentation (Thomas Sjolshagen) 143 - BUG FIX: Use command for git (Thomas Sjolshagen) 144 - BUG FIX: Updating changelog source (Thomas Sjolshagen) 145 - BUG FIX: Reverted CHANGELOG status (Thomas Sjolshagen) 146 - BUG FIX: Separate CHANGELOG and README file generation (Thomas Sjolshagen) 147 - BUG FIX: Updated version number (v3.0.5) (Thomas Sjolshagen) 148 - BUG FIX: Create README.md from the README.txt file (Thomas Sjolshagen) 149 - BUG FIX: Separate CHANGELOG and README file generation (Thomas Sjolshagen) 150 - BUG FIX: Updated README info (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 151 - BUG FIX: Updated version (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 152 - BUG FIX: Didn't include a README.md file for the plugin (Thomas Sjolshagen) 153 - BUG FIX: Update repository name (Thomas Sjolshagen) 154 - BUG FIX: Action triggered twice (Thomas Sjolshagen) 155 - Bug fix/remove debug logging (#6) (Thomas Sjølshagen) 156 - BUG FIX: Re-activate the installed_paths setting for phpcs (Thomas Sjolshagen) 8 157 9 158 ## v3.0.4 - 2021-06-28 … … 151 300 - BUG FIX: Added action hook documentation (Thomas Sjolshagen) 152 301 - BUG FIX: Fix PHPCS warnings (Thomas Sjolshagen) 153 - BUG FIX: Fix PHPCS warnings (Thomas Sjolshagen)154 302 - BUG FIX: Rename e20r_import_load_licensed_modules action hook (Thomas Sjolshagen) 155 303 - BUG FIX: Rename e20r_import_load_licensed_modules action hook and fix PHPCS warnings (Thomas Sjolshagen) … … 224 372 - BUG FIX: Refactored docker-compose.override files for manual testing (Thomas Sjolshagen) 225 373 - BUG FIX: Adding/Updating *ignore files (Thomas Sjolshagen) 226 - BUG FIX: Adding/Updating *ignore files (Thomas Sjolshagen)227 374 - BUG FIX: More updates to support WP Unit testing (Thomas Sjolshagen) 228 375 - BUG FIX: Various updates to support WordPress 'Unit' testing (Thomas Sjolshagen) … … 491 638 * Fixed bugs with static/non-static function calls 492 639 * Enhancement: JavaScript based async loading (for large imports) 640 - BUG FIX: Calculated the wrong timeout value for the JS based background import (Thomas Sjolshagen) 641 - BUG FIX: Updated copyright notice (Thomas Sjolshagen) 642 - BUG FIX: PHPCS was a bit too inclusive (Thomas Sjolshagen) 643 - BUG FIX: Include the README.md file (Thomas Sjolshagen) 644 - BUG FIX: Relocate build status badge (Thomas Sjolshagen) 645 - BUG FIX: Splitting log/doc/updater json generation further (Thomas Sjolshagen) 646 - BUG FIX: Updated CHANGELOG (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 647 - BUG FIX: Error generating documentation (Thomas Sjolshagen) 648 - BUG FIX: Use command for git (Thomas Sjolshagen) 649 - BUG FIX: Updating changelog source (Thomas Sjolshagen) 650 - BUG FIX: Reverted CHANGELOG status (Thomas Sjolshagen) 651 - BUG FIX: Separate CHANGELOG and README file generation (Thomas Sjolshagen) 652 - BUG FIX: Updated version number (v3.0.5) (Thomas Sjolshagen) 653 - BUG FIX: Create README.md from the README.txt file (Thomas Sjolshagen) 654 - BUG FIX: Separate CHANGELOG and README file generation (Thomas Sjolshagen) 655 - BUG FIX: Updated README info (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 656 - BUG FIX: Updated version (v3.0.5 for WP 5.7.2) (Thomas Sjolshagen) 657 - BUG FIX: Didn't include a README.md file for the plugin (Thomas Sjolshagen) 658 - BUG FIX: Update repository name (Thomas Sjolshagen) 659 - BUG FIX: Action triggered twice (Thomas Sjolshagen) 660 - Bug fix/remove debug logging (#6) (Thomas Sjølshagen) 661 - BUG FIX: Re-activate the installed_paths setting for phpcs (Thomas Sjolshagen) -
pmpro-import-members-from-csv/trunk/README.txt
r2555218 r2563515 4 4 Requires at least: 5.0 5 5 Tested up to: 5.7.2 6 Stable tag: 3.0. 46 Stable tag: 3.0.6 7 7 License: GPLv2 8 8 License URI: http://www.gnu.org/licenses/gpl 9 9 10 Import and create user + PMPro member records from a CSV file to your WordPress with Paid Memberships Pro website. Can import the membership information, user meta data, PMPro order data and will link any pre-existing recurring payment records for your payment gateway integration. 10 [](https://github.com/eighty20results/pmpro-import-members-from-csv/actions/workflows/release-plugin.yml) 11 12 Import and create user + PMPro member records from a CSV file on your WordPress with Paid Memberships Pro website. 13 The plugin will import the membership information, user meta data, PMPro order data, Sponsored Members information and 14 can even link pre-existing recurring payment records for your payment gateway integration. 11 15 12 16 == Description == 13 17 14  15 16 This plugin is designed to give you an error free import of a user/member to a WordPress/Paid Memberships Pro site. It supports both adding and changing user data. 17 18 Unlike the "Import User From CSV Integration" add-on by Paid Memberships Pro, this "Import Members from CSV" plugin will verify the data you are trying to import during the import operation. This is done to reduce the probability of problem after the import. If there are any errors/issues,information about the problem will be logged to the pmp_updates.log saved in the `wp-content/uploads/` directory. 19 20 *NOTE*: You can run the import multiple times with the same/slightly modified import .csv file and the appropriate settings (see the FAQ/description below). If you configure the plugin settings correctly, this will only result in overwriting/changing the existing member data. 21 22 Using a CSV (Comma Separated Values) file, the will add users with basic user information as well as user meta data fields, the user role (if applicable) and the specified Paid Memberships Pro member configuration/information. It can also generate an order record to ensure your recurring subscriptions continue to get attributed to the imported member. 23 24 If you've exported the user's passwords as hashed strings, you can import them without re-encrypting them again (by setting the option). 18 We designed this plugin to give you an error free import of a user/member to a WordPress/Paid Memberships Pro site. 19 It supports both adding and changing user data. 20 21 Unlike the "Import User From CSV Integration" add-on by Paid Memberships Pro, this "Import Members from CSV" plugin 22 will verify the data you are trying to import during the import operation. This is done to reduce the probability of 23 problem after the import. If there are any errors/issues, information about the problem will be logged to the 24 `e20r_im_errors.log` saved in the `wp-content/uploads/` directory. 25 26 **NOTE**: You can run the import multiple times with the same/slightly modified import .csv file and the appropriate 27 settings (see the FAQ/description below). If you configure the plugin settings correctly, this will only result in 28 overwriting/changing the existing member data. 29 30 Using a CSV (Comma Separated Values) file, the will add users with basic user information as well as user meta data 31 fields, the user role (if applicable) and the specified Paid Memberships Pro member configuration/information. It can 32 also generate an order record to ensure your recurring subscriptions continue to get attributed to the imported member. 33 34 If you've exported the user's passwords as hashed strings, you can import them without re-encrypting them again 35 (by setting the option). 25 36 26 37 You can also choose to send a notification to the new users and to display password nag on user login. 27 38 28 This plugin supports Network Activation on a WordPress Multisite (WPMU) installation (see the settings page when using in a multisite configuration) 39 This plugin supports Network Activation on a WordPress Multisite (WPMU) installation (see the settings page when 40 using in a multisite configuration) 41 29 42 [Check out my other plugins.](http://eighty20results.com/wordpress-plugins/) 30 43 … … 43 56 * Import hashed password for new/updating users (if the option is selected) 44 57 45 *NOTE*: The plugin may not import some of data if it detects a problem. To find out what the problem was, read this documentation and the FAQ section to ensure you have correctly formatted _all_ of your import data. 46 47 For feature request and bug reports, [please use the issues section on GitHub](https://github.com/eighty20results/import-members-from-csv/issues). 48 Code contributions are welcome [on Github](https://github.com/eighty20results/import-members-from-csv). 49 50 NOTE: In order to hide the "Donation" button after a donation, this plugin will attempt to track the admin's IP address. This action may have GDPR implications for you or your administrators. 51 52 The tracking information is stored in the WordPress options table (wp_options) using the `e20r_import_has_donated` option name and can safely be deleted in the database if you do not wish to leave it. Deleting the option from the database will obviously re-enable the Donation nag. 58 **NOTE**: The plugin may not import some of data if it detects a problem. To find out what the problem was, read this 59 documentation and the FAQ section to ensure you have correctly formatted _all_ of your import data. 60 61 For feature request and bug reports, [please use the issues section on GitHub](https://github.com/eighty20results/pmpro-import-members-from-csv/issues). 62 Code contributions are welcome [on Github](https://github.com/eighty20results/pmpro-import-members-from-csv). 63 64 **NOTE**: In order to hide the "Donation" button after a donation, this plugin will attempt to track the admin's IP 65 address. This action may have GDPR implications for you or your administrators. 66 67 The tracking information is stored in the WordPress options table (wp_options) using the `e20r_import_has_donated` 68 option name and can safely be deleted in the database if you do not wish to leave it. Deleting the option from the 69 database will obviously re-enable the Donation nag. 53 70 54 71 The Nag tracking can be disabled altogether with the `e20r_import_donation_tracking_disabled` filter: … … 68 85 Or use a nifty tool by WordPress lead developer Mark Jaquith: 69 86 70 1. Visit [this link](http://coveredwebservices.com/wp-plugin-install/?plugin=pmpro-import-members-from-csv) and follow the instructions. 87 1. Visit [this link](http://coveredwebservices.com/wp-plugin-install/?plugin=pmpro-import-members-from-csv) and 88 follow the instructions. 71 89 72 90 … … 83 101 1. Upload your CSV file in the 'Memberships' menu, under 'Import Members' 84 102 85 = = Frequently Asked Questions ==86 87 = How to use?=103 = Frequently Asked Questions = 104 105 == How to use? == 88 106 89 107 Click on the 'Import Members' link in the 'Membership' menu, then select your CSV file. 90 108 Next you have to decide whether you: 91 109 92 1. want to deactivate previously existing member record(s) for the user - The CSV record has to specify the same membership as the user previously had so this is most useful when having to reimport/update data (default: enabled and recommended), 93 1. update the existing user/member's information (default: enabled and recommended) 94 1. send a notification email to new users (default: disabled), 95 1. want the password nag to be displayed when the user logs in (default: disabled), 96 1. have included a hashed (encoded) password specified in the import file and (default: disabled) 97 1. want to use the background import option (default: enabled and recommended) 98 1. create a PMPro order record based on supplied payment info in the .csv file (default: disabled) 110 1. want to deactivate previously existing member record(s) for the user - The CSV record has to specify the same 111 membership as the user previously had so this is most useful when having to reimport/update data (default: enabled and 112 recommended), 113 2. update the existing user/member's information (default: enabled and recommended) 114 3. send a notification email to new users (default: disabled), 115 4. want the password nag to be displayed when the user logs in (default: disabled), 116 5. have included a hashed (encoded) password specified in the import file and (default: disabled) 117 6. want to use the background import option (default: enabled and recommended) 118 7. create a PMPro order record based on supplied payment info in the .csv file (default: disabled) 99 119 100 120 Then click the 'Import' button. 101 121 102 122 Each row in your CSV file should represent a user; each column identifies user data, user meta data or user membership data 103 If a column name matches a field in the user table, data from this column is imported in that field; if not, data is imported in a user meta field with the name of the column or into the PMPro custom membership tables. 104 105 Look at the examples/import.csv file in the plugin directory (also linked on the "Import Members" page) to have a better understanding of how the your CSV file should be organized and what the data fields need to contain as far as formatting/values go. 106 107 You can always try importing the examples/import.csv file and look at the result, assuming the values specified for the membership_id in the example file match your membership level configuration. 108 109 = The .CSV file from the "Export to CSV" button on the "Members List" page won't import? = 110 111 The purpose of the resulting .CSV file from the "Export to CSV" is to generate reports that are meaningful to a human, not a file that can be imported easily. This is true for any of the available Import from .CSV plugins/add-ons for Paid Memberships Pro. 112 113 Basically there are a few key differences between the file resulting from the Export function and the file contents needed to import the same member. 123 If a column name matches a field in the user table, data from this column is imported in that field; if not, data is 124 imported in a user meta field with the name of the column or into the PMPro custom membership tables. 125 126 Look at the examples/import.csv file in the plugin directory (also linked on the "Import Members" page) to have a 127 better understanding of how the your CSV file should be organized and what the data fields need to contain as far as 128 formatting/values go. 129 130 You can always try importing the examples/import.csv file and look at the result, assuming the values specified for the 131 membership_id in the example file match your membership level configuration. 132 133 == The .CSV file from the "Export to CSV" button on the "Members List" page won't import? == 134 135 The purpose of the resulting .CSV file from the "Export to CSV" is to generate reports that are meaningful to a human, 136 not a file that can be imported easily. This is true for any of the available Import from .CSV plugins/add-ons for 137 Paid Memberships Pro. 138 139 Basically there are a few key differences between the file resulting from the Export function and the file contents 140 needed to import the same member. 114 141 115 142 As of version 2.5, this plugin includes data checks for some of the more common mistakes I've seen in the .CSV file(s). … … 117 144 You should also check out the import example file that is linked on the "Import Members" page (under the "Choose File" button). 118 145 119 = My import fails, what is wrong? = 120 121 This is almost always related to the data in the file being imported. As a result, I've added some data tests for some of the typical mistakes I've seen in the .CSV file(s) being imported. There is also a link to an example file on the "Import Members" page (under the "Choose File" button) that illustrates a functional import file. Things lik what the field names are and the format you'll most likely need to use for the data in that column. 122 123 Check the wp-content/uploads/pmp_im_errors.log log file for details on the import operations (link should also be included in a wp-admin dashboard notice if there are errors/warnings). The log should contain suggestions on some of the more common mistakes in the data being imported. 124 125 = Do I need to include all the columns from the sample file? = 126 127 No. _Only_ include the columns where you have data to import. I.e, if none of your members need to have their membership end date defined (i.e the membership you're importing doesn't have an expiration or it's a recurring membership with a linked Payment Gateway subscription plan), just remove the column(s) you don't need. That way, the plugin doesn't try to import data that isn't there. 146 == My import fails, what is wrong? == 147 148 This is almost always related to the data in the file being imported. As a result, I've added some data tests for some 149 of the typical mistakes I've seen in the .CSV file(s) being imported. There is also a link to an example file on the 150 "Import Members" page (under the "Choose File" button) that illustrates a functional import file. Things lik what the 151 field names are and the format you'll most likely need to use for the data in that column. 152 153 Check the wp-content/uploads/pmp_im_errors.log log file for details on the import operations (link should also be 154 included in a wp-admin dashboard notice if there are errors/warnings). The log should contain suggestions on some of 155 the more common mistakes in the data being imported. 156 157 == Do I need to include all the columns from the sample file? == 158 159 No. __Only__ include the columns where you have data to import. I.e, if none of your members need to have their 160 membership end date defined (i.e the membership you're importing doesn't have an expiration or it's a recurring 161 membership with a linked Payment Gateway subscription plan), just remove the column(s) you don't need. That way, 162 the plugin doesn't try to import data that isn't there. 128 163 129 164 If a column has no data, you should remove the column and it's column header from the import file! 130 165 131 = The plugin didn't import any membership data!?! = 132 133 This is a pretty common question and the reason is almost always because there is something unexpected in the `membership_` portion of the row being imported. 134 135 Most often it's the date/time format for the membership_startdate and membership_enddate columns. 166 == The plugin didn't import any membership data!?! == 167 168 This is a pretty common question and the reason is almost always because there is something unexpected in the 169 `membership_` portion of the row being imported. 170 171 Most often it's the date/time format for the `membership_startdate` and `membership_enddate` columns. 136 172 137 173 If you use MS Excel(tm) to prepare your .CSV file, you're in for a treat... 138 174 139 In my experience, MS Excel(tm) is _really_ good at changing the date format in a spreadsheet column to whatever it thinks works best (i.e. human readable). 140 141 However, human readable is often problematic for CSV imports, so you *have to ensure* the format follows the YYYY-MM-DD HH:ii:ss (where ii = 2 digit minute value). For startdate I'd recommend using `00:00:00` and for the enddate I'd suggest using `23:59:59`. 142 143 Just to be clear: The _only_ date format for the *membership_startdate*, *membership_enddate* and the *user_registered* columns that this plugin will accept is the MySQL datetime format: YYYY-MM-DD HH:ii:ss. 175 In my experience, MS Excel(tm) is _really_ good at changing the date format in a spreadsheet column to whatever it 176 thinks works best (i.e. human readable). (If my sarcasm doesn't shine through; This actually __isn't__ a good thing!) 177 178 However, human readable is often problematic for CSV imports, so you **have to make sure** the date format follows the 179 `YYYY-MM-DD HH:ii:ss` template (where ii = 2 digit minute value). For startdate I'd recommend using `00:00:00` and 180 for the enddate I'd suggest using `23:59:59`. 181 182 Just to be clear: The __only__ date format for the `membership_startdate`, `membership_enddate` and the 183 `user_registered` columns that this plugin will accept is the MySQL datetime format: YYYY-MM-DD HH:ii:ss. 144 184 145 185 *Use anything else and your membership data will not be imported*! 146 186 147 You can change the way Microsoft Excel(tm) handles date and time data in the Regional settings, but I've yet to figure out what the ideal settings are here. Truth be told, I'm using Apple Numbers and others have had great success using Google Sheets to process and export their .CSV files. Because there are alternatives to Microsoft Excel(tm) and they seem to work a lot better for this specific task, I'm not at all inclined to spend more time on fixing something that I view to be a rather significant "bug"[1] in Excel(tm). 148 149 [1] = Being that it's an intentional usability feature, I realize Microsoft is unlikely to be all that interested in fixing this "as designed" capability they've implemented. 150 = Can this plugin be used to link sponsored members with their sponsors? = 187 You can change the way Microsoft Excel(tm) handles date and time data in the Regional settings, but I've yet to 188 figure out what the ideal settings are here. Truth be told, I'm using Apple Numbers and others have had great 189 success using Google Sheets to process and export their .CSV files. Because there are alternatives to Microsoft 190 Excel(tm) and they seem to work a lot better for this specific task, I'm not at all inclined to spend more time 191 on fixing something that I view to be a rather significant "bug"[1] in Excel(tm). 192 193 [1] = Being that it's an intentional usability feature, I realize Microsoft is unlikely to be all that interested 194 in fixing this "as designed" capability they've implemented. 195 196 == Can this plugin be used to link sponsored members with their sponsors? == 151 197 152 198 Yes. 153 199 154 In version 2.60, we added support for importing Sponsors and their sponsored members. So, if you have the PMPro Sponsored Members add-on installed, active and need to link sponsors and their sponsored members during the import with this plugin. 200 In version 2.60, we added support for importing Sponsors and their sponsored members. So, if you have the 201 PMPro Sponsored Members add-on installed, active and need to link sponsors and their sponsored members 202 during the import with this plugin. 155 203 156 204 == Importing the Sponsored user == … … 158 206 To link sponsored users with their sponsors, add the `pmprosm_sponsor` column to your import file. 159 207 160 On the data row for the _sponsored_ user, the pmprosm_sponsor column must contain the user key for the sponsor you want to link them with. 208 On the data row for the __sponsored__ user, the `pmprosm_sponsor` column must contain the user key for the sponsor 209 you want to link them with. 161 210 162 211 Or, if they don't have a sponsor, that column must be blank. 163 212 164 The sponsor key is either the email address they used when registering on your system - or the user_email column value for their user record if they're also being imported at the same time, the WordPress user ID value (numeric), or the login name used (user_login value). 213 The sponsor key is either the email address they used when registering on your system - or the user_email column 214 value for their user record if they're also being imported at the same time, the WordPress user ID value (numeric), 215 or the login name used (user_login value). 165 216 166 217 == Importing the Sponsor == 167 218 168 First of all, you will need to include a `pmprosm_seats` column as well. This column contains a numeric value to indicate the number of seats (sponsored users) this user has paid to sponsor. 219 First of all, you will need to include a `pmprosm_seats` column as well. This column contains a numeric value to 220 indicate the number of seats (sponsored users) this user has paid to sponsor. 169 221 170 222 When importing a sponsor there are a couple of scenarios; 171 223 172 1) The system already contains the sponsor code (a sponsor code is a PMPro discount code prefixed with the letter 'S') and you simply need to link the sponsor to their code. 224 1) The system already contains the sponsor code (a sponsor code is a PMPro discount code prefixed with the letter 'S') 225 and you simply need to link the sponsor to their code. 173 226 174 227 2) The system lacks the sponsor code, so you'll need one to be created. 175 228 176 For scenario 1; The sponsor code (discount code) already has a Discount Code ID (integer value, found on the PMPro "Discount Codes" settings page). This ID needs to be added in the `membership_code_id` column of the import file for the sponsor (user record), along with a numeric value in the `pmprosm_seats` column. 177 178 For scenario 2; The sponsor code is created by this plugin. It happens automatically if the sponsor user exists - or is being imported at the same time as - when the *sponsored* user is attempted imported and linked. The discount code created attempts to use the settings from the PMPro Sponsored Members add-on for the discount code. 229 For scenario 1; The sponsor code (discount code) already has a Discount Code ID (integer value, found on the PMPro 230 "Discount Codes" settings page). This ID needs to be added in the `membership_code_id` column of the import file for 231 the sponsor (user record), along with a numeric value in the `pmprosm_seats` column. 232 233 For scenario 2; The sponsor code is created by this plugin. It happens automatically if the sponsor user exists - or 234 is being imported at the same time as - when the **sponsored** user is attempted imported and linked. The discount 235 code created attempts to use the settings from the PMPro Sponsored Members add-on for the discount code. 179 236 180 237 === Caveat === … … 182 239 The order in which users are listed in the .csv import file can matter when importing sponsors and their sponsored user. 183 240 184 Although this plugin tries to re-import sponsored users if the import fails the first time, as part of the clean-up process, this retry does not guarantee success! 241 Although this plugin tries to re-import sponsored users if the import fails the first time, as part of the 242 clean-up process, this retry does not guarantee success! 185 243 186 244 As a result, it is possible that a sponsored user is imported without being linked to their sponsor. … … 198 256 As of version 2.20, we have an option to create member orders at the same time as we update the membership record. 199 257 200 That means you can now include some of the order table fields to import custom values as needed for each user/member, along with updating/adding their membership level information. 258 That means you can now include some of the order table fields to import custom values as needed for each 259 user/member, along with updating/adding their membership level information. 201 260 202 261 The supported order record columns are: … … 231 290 1. billing_phone (*) 232 291 233 All of these columns/fields should be prefixed with 'membership_'. I.e. 'membership_paypal_token' or 'membership_tax', etc. The exceptions are the 'user_id' and 'membership_id' columns/fields which should be left as 'user_id' and 'membership_id' respectively if you want to include them in the import operation(s). 234 235 The 'status' column has a limited number of valid values. By default, we recommend using either 'success' or 'cancelled' 236 237 All timestamp values ('timestamp') must use the same format as the one used by the MySQL database's 'DATETIME' format: `YYYY-MM-DD HH:MM:SS` 238 239 *PLEASE NOTE:* 240 241 Although you _can_ specify an account number (accountnumber) in the import file, doing that will *not* result in this plugin importing and activating subscriptions or payments by credit card. 242 243 You CANNOT use this tool to import and *create* subscription plans, or transactions, on the payment gateway for your Paid Memberships Pro users. 244 245 Including anything other than a masked Credit Card number for the "membership_accountnumber" column *is a really bad idea*[1]! 246 247 A masked credit card number = Only the last 4 digits are real and the rest are repetitions of the 'X' character (XXXXXXXXXXXX1234). 248 249 [1] = Importing a full credit card number will exponentially increase the probability that you, in the event of a security problem on your site, will have to pay the Payment Card Industry (PCI) massive fines. Simply put; Don't import Credit Card information! Instead, ask your members to resubmit their information when the site is back online/live. 250 251 *This plugin does NOT mask your credit card numbers for you!* 252 253 = Supported membership_gateway options = 254 255 The Import Members from CSV plugin supports specifying different payment gateways for the user record(s) when importing order data (i.e. the "Attempt to create PMPro Order record" option has been selected). At present, the payment gateways that can be specified in the `membership_gateway` column are: 292 All of these columns/fields should be prefixed with `membership_`. I.e. `membership_paypal_token` or `membership_tax`, 293 etc. The exceptions are the `user_id` and `membership_id` columns/fields which should be left as `user_id` and 294 `membership_id` respectively if you want to include them in the import operation(s). 295 296 The `status` column has a limited number of valid values. By default, we recommend using either `success` or `cancelled` 297 298 All timestamp values ('timestamp') must use the same format as the one used by the MySQL database's 'DATETIME' 299 format: `YYYY-MM-DD HH:MM:SS` 300 301 **PLEASE NOTE:** 302 303 Although you _can_ specify an account number (`accountnumber`) in the import file, doing that will *not* result in 304 this plugin importing and activating subscriptions or payments by credit card. 305 306 You CANNOT use this tool to import and **create** subscription plans, or transactions, on the payment gateway for 307 your Paid Memberships Pro users. 308 309 Including anything other than a masked Credit Card number for the `membership_accountnumber` column *is a really 310 bad idea*[1]! 311 312 A masked credit card number = Only the last 4 digits are real and the rest are repetitions of the 'X' 313 character (`XXXXXXXXXXXX1234`). 314 315 [1] = Importing a full credit card number will exponentially increase the probability that you, in the event of a 316 security problem on your site, will have to pay the Payment Card Industry (PCI) massive fines. Simply put; Don't import 317 Credit Card information! Instead, ask your members to resubmit their information when the site is back online/live. 318 319 **This plugin does NOT mask your credit card numbers for you!** 320 321 == Supported membership_gateway options == 322 323 The Import Members from CSV plugin supports specifying different payment gateways for the user record(s) when 324 importing order data (i.e. the "Attempt to create PMPro Order record" option has been selected). At present, the 325 payment gateways that can be specified in the `membership_gateway` column are: 256 326 257 327 1. authorizenet 258 1. braintree 259 1. check 260 1. cybersource 261 1. payflowpro 262 1. paypal 263 1. paypalexpress 264 1. paypalstandard 265 1. stripe 266 1. twocheckout 267 268 During the import operation, the plugin will verify that the specified payment gateway integration is one of the supported payment gateway integrations for Paid Memberships Pro. 269 270 Specifying a Payment Gateway Integration that has not been configured for use during the PMPro checkout process would render the order record invalid. 271 272 NOTE: The limitations to how Paid Memberships Pro supports/handles multiple payment gateway integrations at the same time still apply. 273 274 = Adding billing address information to the PMPro Order import = 275 276 The normal way to import billing address data to the database for a member/user is to use the `pmpro_b[*]` fields (pmpro_bfirstname, pmpro_blastname, pmpro_baddress1, pmpro_baddress2, pmpro_bcity, pmpro_bstate, pmpro_bzipcode, pmpro_bcountry and pmpro_bphone). 277 278 If the pmpro_b* field data is present in the row and the 'Add order' option is selected for the import file, the import will attempt to populate the order billing information using the pmpro_b* data. 328 2. braintree 329 3. check 330 4. cybersource 331 5. payflowpro 332 6. paypal 333 7. paypalexpress 334 8. paypalstandard 335 9. stripe 336 10. twocheckout 337 11. payfast 338 339 During the import operation, the plugin will verify that the specified payment gateway integration is one of the 340 supported payment gateway integrations for Paid Memberships Pro. 341 342 Specifying a Payment Gateway Integration that has not been configured for use during the PMPro checkout process would 343 render the order record invalid. 344 345 **NOTE:** The limitations to how Paid Memberships Pro supports/handles multiple payment gateway integrations at the 346 same time still apply. 347 348 == Adding billing address information to the PMPro Order import == 349 350 The normal way to import billing address data to the database for a member/user is to use the `pmpro_b[*]` fields 351 (`pmpro_bfirstname`, `pmpro_blastname`, `pmpro_baddress1`, `pmpro_baddress2`, `pmpro_bcity`, `pmpro_bstate`, 352 `pmpro_bzipcode`, `pmpro_bcountry` and `pmpro_bphone`). 353 354 If the `pmpro_b*` field data is present in the row and the 'Add order' option is selected for the import file, the 355 import will attempt to populate the order billing information using the `pmpro_b*` data. 279 356 280 357 = How should the .csv file be defined? = … … 287 364 288 365 For example; 289 To have a 2 column .csv file, each row **after** the header row, the row should look something like this: `"my first column data","my second \"escaped\" column data"`. 290 291 The application you use to edit and export your .CSV file will need to be configured appropriately before you export the .csv file. 366 To have a 2 column .csv file, each row **after** the header row, the row should look something like this: 367 `"my first column data","my second \"escaped\" column data"`. 368 369 The application you use to edit and export your .CSV file will need to be configured appropriately before you 370 export the .csv file. 292 371 293 372 = Why am I or my users not receiving New user notifications = 294 373 295 There are a couple of possible reasons, as far as I can tell. The functionality in WordPress that generates the "new user notification" message is what they call "pluggable". That means that it's possible for a plugin (any plugin!) to override the behavior of the functionality. So the first thing I'd suggest investigating is whether you have a pluing active that intentionally changes/modifies/updates how the `wp_new_user_notification()` function works/behaves. 296 297 Next, it's (very) possible that your hosting environment doesn't want you to be sending out a lot of email messages from their servers. As a result, the import operation could potentially trip their anti-spam measures and blocking you from sending any messages. 298 299 Third, the recipient email server may be using a SBL (Spam Black List) and have your web server IP listed as a typical source of Spam messages (it happens, a lot). 300 301 = I've set the 'membership_status' column to 'inactive', but the user's imported membership level is currently 'active'? = 374 There are a couple of possible reasons, as far as I can tell. The functionality in WordPress that generates the 375 "new user notification" message is what they call "pluggable". That means that it's possible for a plugin (any plugin!) 376 to override the behavior of the functionality. So the first thing I'd suggest investigating is whether you have a 377 plugin active that intentionally changes/modifies/updates how the `wp_new_user_notification()` function works/behaves. 378 379 Next, it's (very) possible that your hosting environment doesn't want you to be sending out a lot of email messages 380 from their servers. As a result, the import operation could potentially trip their anti-spam measures and blocking 381 you from sending any messages. 382 383 Third, the recipient email server may be using a SBL (Spam Black List) and have your web server IP listed as a 384 typical source of Spam messages (it happens, a lot). 385 386 == I've set the 'membership_status' column to 'inactive', but the user's imported membership level is currently 'active'? == 302 387 303 388 This is due to what I'd term a bug in Paid Memberships Pro. This issue doesn't currently have a fix. 304 389 305 Basically, the 'inactive' status will only apply to the order record (if it's created, see above) and *not* to the user's membership status. 306 307 NOTE: Assigning a membership level for a user will cause them to be given an active membership on the site when the import operation is complete, regardless of the value supplied for the 'membership_status' column. 308 309 = How do I import an existing payment plan (recurring billing plan) for a user? = 390 Basically, the 'inactive' status will only apply to the order record (if it's created, see above) and *not* to the 391 user's membership status. 392 393 **NOTE:** Assigning a membership level for a user will cause them to be given an active membership on the site when 394 the import operation is complete, regardless of the value supplied for the 'membership_status' column. 395 396 == How do I import an existing payment plan (recurring billing plan) for a user? == 310 397 311 398 This only works if the plan already exists on the payment gateway itself. 312 399 313 There is no way to use this plugin to import a new member/user and have the system create a recurring billing plan for them. 314 315 = Can I use this plugin to create new billing plans or trigger charges on the payment gateway for an imported user? = 400 There is no way to use this plugin to import a new member/user and have the system create a recurring billing plan 401 for them. 402 403 == Can I use this plugin to create new billing plans or trigger charges on the payment gateway for an imported user? == 316 404 317 405 No. 318 406 319 = What are the constraints for WordPress Multisite import operations?=407 == What are the constraints for WordPress Multisite import operations? == 320 408 321 409 As documented by Paid Memberships Pro, the PMPro plugin cannot be Network Activated. 322 410 323 This import plugin will work from the site(s) where PMPro is active _and_ have the same membership level IDs identified as are listed in the `membership_id` column of the import file you're using. 324 325 If your primary site has a configured and active Paid Memberships Pro installation, you could theoretically start the plugin from the Network Admin dashboard (which will send you to the primary site anyway). 326 327 The users being imported will only be linked to the site you import them to. Their membership data will only be visible on the PMPro site(s) that have the membership level ID(s) configured that match those in the import file. 411 This import plugin will work from the site(s) where PMPro is active _and_ have the same membership level IDs 412 identified as are listed in the `membership_id` column of the import file you're using. 413 414 If your primary site has a configured and active Paid Memberships Pro installation, you could theoretically start 415 the plugin from the Network Admin dashboard (which will send you to the primary site anyway). 416 417 The users being imported will only be linked to the site you import them to. Their membership data will only be 418 visible on the PMPro site(s) that have the membership level ID(s) configured that match those in the import file. 328 419 329 420 = Welcome Email Message (imported_welcome.html template) issues = … … 332 423 please make sure the 'membership_status' field is included in the import .csv file and contains the `active` value. 333 424 334 As a design philosophy, we treat an inactive member as somebody who should _not_ receive welcome messages (you may disagree..?) 335 336 = What GDPR impacted data is stored by this plugin? = 337 338 Obviously, there's the user data that this plugin is designed to import. This plugin does _not_ track, report, or allow download/deletion of any data it imports. There are (now or soon) other plugin options to handle those requirements from the GDPR legislation. 339 340 In an attempt to make the "Donation" button less intrusive, we attempt to track the computer (IP) address when somebody clicks the button. This plugin does _not_ link the IP address to a user account, so it should be a little more challenging to identify the person who clicked the "Donate" button for any 3rd party who gets access to your database than simply looking at the options saved by this plugin. 341 342 The IP tracking information (the IP address) is stored in the WordPress options table (`wp_options`) using the `e20r_import_has_donated` option name. That option can safely be deleted in the database if you do not wish to have IPs tracked. Deleting the option from the database will obviously re-enable the Donation nag. 343 344 As long as this plugin remains installed and active on the server, the tracked IP address will automatically be removed from the option 2 months after the admin clicked the Donation button. 425 As a design philosophy, we treat an inactive member as somebody who should _not_ receive welcome messages 426 (you may disagree..?) 427 428 == What GDPR impacted data is stored by this plugin? == 429 430 Obviously, there's the user data that this plugin is designed to import. This plugin does _not_ track, report, or 431 allow download/deletion of any data it imports. There are (now or soon) other plugin options to handle those 432 requirements from the GDPR legislation. 433 434 In an attempt to make the "Donation" button less intrusive, we attempt to track the computer (IP) address when 435 somebody clicks the button. This plugin does _not_ link the IP address to a user account, so it should be a little 436 more challenging to identify the person who clicked the "Donate" button for any 3rd party who gets access to your 437 database than simply looking at the options saved by this plugin. 438 439 The IP tracking information (the IP address) is stored in the WordPress options table (`wp_options`) using the 440 `e20r_import_has_donated` option name. That option can safely be deleted in the database if you do not wish to have 441 IPs tracked. Deleting the option from the database will obviously re-enable the Donation nag. 442 443 As long as this plugin remains installed and active on the server, the tracked IP address will automatically be 444 removed from the option 2 months after the admin clicked the Donation button. 345 445 346 446 The option is removed when the plugin is deactivated in the "Plugins" admin panel. 347 447 348 Nag tracking can be disabled altogether with the `e20r_import_donation_tracking_disabled` filter: `add_filter( 'e20r_import_donation_tracking_disabled', '__return_true' );'` 448 Nag tracking can be disabled altogether with the `e20r_import_donation_tracking_disabled` filter: 449 `add_filter( 'e20r_import_donation_tracking_disabled', '__return_true' );'` 349 450 350 451 == Installation == 351 452 352 453 1. Upload the `pmpro-import-members-from-csv` folder to the `/wp-content/plugins/` directory. 353 1. Activate the plugin through the 'Plugins' menu in WordPress.454 2. Activate the plugin through the 'Plugins' menu in WordPress. 354 455 355 456 == Screenshots == 356 457 357 458 1. User import screen 358 1. Ongoing (background) import screen359 1. Default settings on the user import screen459 2. Ongoing (background) import screen 460 3. Default settings on the user import screen 360 461 361 462 == Known Issues == … … 369 470 == Supported Filters and Actions == 370 471 371 The list of filters and actions supported by this plugin can be found in the [Filters](./docs/FILTERS.md) and [Actions](./docs/ACTIONS.md) documentation. 472 The list of filters and actions supported by this plugin can be found in the [Filters](./docs/FILTERS.md) and 473 [Actions](./docs/ACTIONS.md) documentation. -
pmpro-import-members-from-csv/trunk/class.pmpro-import-members.php
r2555218 r2563515 1 <?php 1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName 2 2 /** 3 3 Plugin Name: Import Paid Memberships Pro Members from CSV 4 4 Plugin URI: http://wordpress.org/plugins/pmpro-import-members-from-csv/ 5 5 Description: Import Users and their metadata from a csv file. 6 Version: 3.0. 46 Version: 3.0.6 7 7 Requires PHP: 7.3 8 8 Author: <a href="https://eighty20results.com/thomas-sjolshagen/">Thomas Sjolshagen <[email protected]></a> … … 42 42 use function plugin_dir_path; 43 43 use function add_action; 44 use function error_log; 44 use function error_log; // phpcs:ignore 45 45 46 46 if ( ! defined( 'E20R_IM_CSV_DELIMITER' ) ) { … … 55 55 56 56 if ( ! defined( 'E20R_IMPORT_VERSION' ) ) { 57 define( 'E20R_IMPORT_VERSION', '3.0. 4' );58 } 59 60 require_once plugin_dir_path( __FILE__ ) . ' /ActivateUtilitiesPlugin.php';57 define( 'E20R_IMPORT_VERSION', '3.0.6' ); 58 } 59 60 require_once plugin_dir_path( __FILE__ ) . 'class-activateutilitiesplugin.php'; 61 61 62 62 /** … … 107 107 foreach ( $base_paths as $base_path ) { 108 108 109 $iterator = new RecursiveDirectoryIterator( 110 $base_path, 111 RecursiveDirectoryIterator::SKIP_DOTS | 112 RecursiveIteratorIterator::SELF_FIRST | 113 RecursiveIteratorIterator::CATCH_GET_CHILD | 114 RecursiveDirectoryIterator::FOLLOW_SYMLINKS 115 ); 116 117 $filter = new RecursiveCallbackFilterIterator( 118 $iterator, 119 function ( $current, $key, $iterator ) use ( $filename ) { 120 121 // Skip hidden files and directories. 122 if ( $current->getFilename()[0] === '.' || $current->getFilename() === '..' ) { 123 return false; 109 try { 110 $iterator = new RecursiveDirectoryIterator( 111 $base_path, 112 RecursiveDirectoryIterator::SKIP_DOTS | 113 RecursiveIteratorIterator::SELF_FIRST | 114 RecursiveIteratorIterator::CATCH_GET_CHILD | 115 RecursiveDirectoryIterator::FOLLOW_SYMLINKS 116 ); 117 } catch ( \Exception $e ) { 118 print 'Error: ' . $e->getMessage(); // phpcs:ignore 119 return; 120 } 121 122 try { 123 $filter = new RecursiveCallbackFilterIterator( 124 $iterator, 125 function ( $current, $key, $iterator ) use ( $filename ) { 126 127 // Skip hidden files and directories. 128 if ( '.' === $current->getFilename()[0] || '..' === $current->getFilename() ) { 129 return false; 130 } 131 132 if ( $current->isDir() ) { 133 // Only recurse into intended subdirectories. 134 return $current->getFilename() === $filename; 135 } else { 136 // Only consume files of interest. 137 return str_starts_with( $current->getFilename(), $filename ); 138 } 124 139 } 125 126 if ( $current->isDir() ) { 127 // Only recurse into intended subdirectories. 128 return $current->getFilename() === $filename; 129 } else { 130 // Only consume files of interest. 131 return str_starts_with( $current->getFilename(), $filename ); 132 } 133 } 134 ); 140 ); 141 } catch ( \Exception $e ) { 142 echo 'Autoloader error: ' . $e->getMessage(); // phpcs:ignore 143 return; 144 } 135 145 136 146 foreach ( new RecursiveIteratorIterator( $iterator ) as $f_filename => $f_file ) { -
pmpro-import-members-from-csv/trunk/docker-compose.yml
r2554806 r2563515 19 19 ports: 20 20 - ${WP_PORT}:80 21 stdin_open: true # docker run -i 22 tty: true # docker run -t 21 23 command: 22 24 - /bin/sh … … 57 59 MYSQL_RANDOM_ROOT_PASSWORD: ${MYSQL_RANDOM_ROOT_PASSWORD} 58 60 volumes: 59 - ${LOCAL_PLUGIN_DIR} :/docker-entrypoint-initdb.d61 - ${LOCAL_PLUGIN_DIR}/tests/_data:/docker-entrypoint-initdb.d -
pmpro-import-members-from-csv/trunk/javascript/pmpro-import-members-from-csv.js
r2554806 r2563515 1 1 /** 2 * Copyright (c) 2018 -2019- Eighty / 20 Results by Wicked Strong Chicks.2 * Copyright (c) 2018 - 2021 - Eighty / 20 Results by Wicked Strong Chicks. 3 3 * ALL RIGHTS RESERVED 4 4 * -
pmpro-import-members-from-csv/trunk/src/class-data.php
r2554806 r2563515 82 82 // Add PMPro info as applicable 83 83 if ( ! empty( $user ) ) { 84 // @phpstan-ignore-next-line 84 85 $user->membership_level = ( 85 86 function_exists( 'pmpro_getMembershipLevelForUser' ) ? … … 88 89 ); 89 90 91 // @phpstan-ignore-next-line 90 92 $user->membership_levels = ( 91 93 function_exists( 'pmpro_getMembershipLevelsForUser' ) ? … … 332 334 333 335 if ( ! in_array( $billing_field_name, array_keys( $billing_fields ), true ) ) { 334 return null;336 return false; 335 337 } 336 338 -
pmpro-import-members-from-csv/trunk/src/class-email-templates.php
r2554806 r2563515 76 76 77 77 // Email 'your membership account is active' to member if they were imported with an active member status 78 if ( true === (bool) $send_email && 79 isset( $fields['membership_status'] ) && 'active' === $fields['membership_status'] && 80 1 === version_compare( PMPRO_VERSION, '1.9.5' ) 78 if ( 79 true === (bool) $send_email && 80 isset( $fields['membership_status'] ) && 'active' === $fields['membership_status'] && 81 // @phpstan-ignore-next-line 82 1 === version_compare( PMPRO_VERSION, '1.9.5' ) 81 83 ) { 82 84 $subject = null; … … 103 105 $this->error_log->debug( "Using {$template_name} template for '{$subject}' message" ); 104 106 107 // PMPro is not good at defining properties in classes (badly reliant on the historically dynamic nature of PHP) 108 // so will have PHPStan ignore these lines until PMPro cleans up their stuff 109 // (i.e. TODO when PMPro takes better advantage of PHP) 105 110 $email = new \PMProEmail(); 106 $email->email = $user->user_email; 107 $email->data = apply_filters( 'pmp_im_imported_member_message_data', array() ); 108 $email->subject = $subject; 109 $email->template = $template_name; 111 $email->email = $user->user_email; // @phpstan-ignore-line 112 $email->data = apply_filters( 'pmp_im_imported_member_message_data', array() ); // @phpstan-ignore-line 113 $email->subject = $subject; // @phpstan-ignore-line 114 $email->template = $template_name; // @phpstan-ignore-line 110 115 111 116 if ( ! empty( $body ) ) { 112 $email->body = $body; 117 $email->body = $body; // @phpstan-ignore-line 113 118 } else { 114 $email->body = $this->load_email_body( null, $email->template ); 119 $email->body = $this->load_email_body( null, $email->template ); // @phpstan-ignore-line 115 120 } 116 121 117 122 $email->body = apply_filters( 'pmp_im_imported_member_message_body', $email->body ); 123 $email->body = apply_filters( 'e20r_import_member_message_body', $email->body ); 118 124 119 125 // Process and send email … … 228 234 foreach ( $locations as $path ) { 229 235 if ( true === file_exists( $path ) ) { 230 $body = file_get_contents( $path ); 236 $body = file_get_contents( $path ); // phpcs:ignore 231 237 break; 232 238 } … … 265 271 'subject' => __( 'Welcome to my new website', 'pmpro-import-members-from-csv' ), 266 272 'description' => __( 'Import: Welcome Member', 'pmpro-import-members-from-csv' ), 273 // phpcs:ignore 267 274 'body' => file_get_contents( Import_Members::$plugin_path . '/emails/imported_member.html' ), 268 275 ); -
pmpro-import-members-from-csv/trunk/src/class-error-log.php
r2554806 r2563515 67 67 'error' 68 68 ); 69 69 return; 70 70 } 71 71 … … 146 146 * Identify the calling function (used in debug logger 147 147 * 148 * @return array|string148 * @return string 149 149 * 150 150 * @access public 151 151 */ 152 private function who_called_me() {152 private function who_called_me() : string { 153 153 $trace = debug_backtrace(); // phpcs:ignore 154 154 $caller = $trace[2]; -
pmpro-import-members-from-csv/trunk/src/class-import-members.php
r2554946 r2563515 144 144 145 145 if ( false === apply_filters( 'e20r_utilities_module_installed', false ) ) { 146 add_action( 'init', '\E20R\Import\Loader::is_utilities_module_active', 10 );147 } 148 add_action( 'plugins_loaded', array( Email_Templates::get_instance(), 'load_hooks' ), 99 );149 add_action( 'plugins_loaded', array( Ajax::get_instance(), 'load_hooks' ), 99 );150 add_action( 'plugins_loaded', array( Page::get_instance(), 'load_hooks' ), 99 );146 add_action( 'init', '\E20R\Import\Loader::is_utilities_module_active', 10, 0 ); 147 } 148 add_action( 'plugins_loaded', array( Email_Templates::get_instance(), 'load_hooks' ), 99, 0 ); 149 add_action( 'plugins_loaded', array( Ajax::get_instance(), 'load_hooks' ), 99, 0 ); 150 add_action( 'plugins_loaded', array( Page::get_instance(), 'load_hooks' ), 99, 0 ); 151 151 152 152 // Add validation logic for all modules 153 add_action( 'plugins_loaded', array( User_Validation::get_instance(), 'load_actions' ), 30 );154 add_action( 'plugins_loaded', array( PMPro_Validation::get_instance(), 'load_actions' ), 31 );155 add_action( 'plugins_loaded', array( BuddyPress_Validation::get_instance(), 'load_actions' ), 32 );156 157 add_action( 'init', array( $this, 'load_i18n' ), 5 );158 add_action( 'init', array( $this->data, 'process_csv' ) );159 160 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );161 162 // PMPro specific import functionality163 // phpcs:ignore -We do this in the CSV() class as it's a clean-up operation164 // add_action( 'e20r_before_user_import', array( $this->csv, 'pre_import' ), 10, 2 ); 153 add_action( 'plugins_loaded', array( User_Validation::get_instance(), 'load_actions' ), 30, 0 ); 154 add_action( 'plugins_loaded', array( PMPro_Validation::get_instance(), 'load_actions' ), 31, 0 ); 155 add_action( 'plugins_loaded', array( BuddyPress_Validation::get_instance(), 'load_actions' ), 32, 0 ); 156 157 add_action( 'init', array( $this, 'load_i18n' ), 5, 0 ); 158 add_action( 'init', array( $this->data, 'process_csv' ), 10, 0 ); 159 160 add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ), 10, 0 ); 161 162 // PMPro specific capabilities 163 // We do this in the CSV() class as it's a clean-up operation 164 // add_action( 'e20r_before_user_import', array( $this->csv, 'pre_import' ), 10, 2 ); // phpcs:ignore 165 165 add_filter( 'e20r_import_usermeta', array( $this->import_user, 'import_usermeta' ), 10, 2 ); 166 166 add_action( … … 179 179 180 180 // Clear action handler(s) from the Import Users from CSV Integration Add-on for PMPro 181 add_action( 'wp_loaded', array( $this, 'remove_iucsv_support' ), 10 );181 add_action( 'wp_loaded', array( $this, 'remove_iucsv_support' ), 10, 0 ); 182 182 183 183 // Remove Import action for Sponsored Members add-on (handled directly by this plugin) 184 184 remove_action( 'is_iu_post_user_import', 'pmprosm_is_iu_post_user_import', 20 ); 185 185 186 if ( class_exists( 'E20R\Utilities\Licensing\Licensing' ) ) { 187 $licensing = new Licensing( self::E20R_LICENSE_SKU ); 188 189 if ( $licensing->is_licensed( self::E20R_LICENSE_SKU, false ) ) { 190 do_action( 'e20r_import_load_licensed_modules' ); 191 } 186 if ( ! class_exists( 'E20R\Utilities\Licensing\Licensing' ) ) { 187 return; 188 } 189 190 $check = new \ReflectionMethod( 'E20R\Utilities\Licensing\Licensing', '__construct' ); 191 192 if ( false === $check->isPrivate() ) { 193 $licensing = new Licensing( self::E20R_LICENSE_SKU ); 194 $is_licensed = $licensing->is_licensed( self::E20R_LICENSE_SKU, false ); 195 } else { 196 // @phpstan-ignore-next-line 197 $is_licensed = Licensing::is_licensed( self::E20R_LICENSE_SKU, false ); 198 } 199 200 if ( true === $is_licensed ) { 201 do_action( 'e20r_import_load_licensed_modules' ); 192 202 } 193 203 } … … 249 259 */ 250 260 $max_run_time = ( 251 apply_filters( 'pmp_im_import_time_per_record', 3) *252 apply_filters( ' pmp_im_import_records_per_scan', $this->variables->get( 'per_partial' ) )261 $this->variables->calculate_per_record_time() * 262 apply_filters( 'e20r_import_records_per_scan', $this->variables->get( 'per_partial' ) ) 253 263 ); 254 264 … … 261 271 'pmpro-import-members-from-csv', 262 272 plugins_url( 'css/pmpro-import-members-from-csv.css', E20R_IMPORT_PLUGIN_FILE ), 263 null,273 array(), 264 274 E20R_IMPORT_VERSION 265 275 ); 276 266 277 // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NotInFooter 267 278 wp_register_script( … … 358 369 public function plugin_row_meta( $links, $file ) { 359 370 360 if ( true === stripos( $file, 'class.pmpro-import-members.php' ) ) {371 if ( false !== stripos( $file, 'class.pmpro-import-members.php' ) ) { 361 372 // Add (new) 'Import Users from CSV' links to plugin listing 362 373 $new_links = array( -
pmpro-import-members-from-csv/trunk/src/class-variables.php
r2554806 r2563515 302 302 $this->error_log->debug( "File name from transient is {$this->filename} vs tmp name of {$tmp_name}" ); 303 303 304 if ( empty( $ filename ) && ( ! empty( $tmp_name ) && file_exists( $tmp_name ) ) ) {304 if ( empty( $this->filename ) && ( ! empty( $tmp_name ) && file_exists( $tmp_name ) ) ) { 305 305 306 306 $this->error_log->debug( "Update/move the {$tmp_name} file!" ); … … 312 312 exit(); 313 313 } 314 } elseif ( ! empty( $filename ) ) {315 $this->filename = $filename;316 314 } 317 315 … … 345 343 346 344 if ( ! empty( $max_exec_time ) && ( is_numeric( $per_record_time ) ) ) { 347 $this->per_partial = round( ceil( $max_exec_time / (float) $per_record_time ), 0);345 $this->per_partial = intval( round( ceil( $max_exec_time / (float) $per_record_time ), 0 ) ); 348 346 } 349 347 -
pmpro-import-members-from-csv/trunk/src/import/class-ajax.php
r2554946 r2563515 119 119 $this->error_log->debug( "Visitor ({$client_ip}) clicked the 'Donate' button" ); 120 120 wp_send_json_success(); 121 exit();122 121 } 123 122 } 124 123 125 124 wp_send_json_error(); 126 exit();127 125 } 128 126 … … 162 160 if ( false === $this->delete_file( $logfile_path ) ) { 163 161 wp_send_json_error(); 164 exit();165 162 } 166 163 167 164 // Return success 168 165 wp_send_json_success(); 169 exit();170 166 } 171 167 … … 186 182 $this->error_log->debug( 'File not found/not available. Nothing to clean!' ); 187 183 wp_send_json_success(); 188 exit();189 184 } 190 185 … … 197 192 198 193 wp_send_json_error(); 199 exit();200 194 } 201 195 … … 208 202 209 203 wp_send_json_success(); 210 exit();211 204 } 212 205 … … 244 237 $this->error_log->debug( 'Nonce verified in import_members_from_csv()' ); 245 238 246 /* 239 /* @codingStandardsIgnoreStart 240 * 247 241 if ( false === wp_verify_nonce( $_REQUEST['e20r-im-import-members-wpnonce'], 'e20r-im-import-members' ) ) { 248 242 249 243 $msg = __( 'Insecure connection attempted!', 'pmpro-import-members-from-csv' ); 250 244 251 wp_send_json_error( array( 'status' => - 1, 252 'message' => $msg, 253 ) ); 254 exit(); 255 } 256 */ 245 wp_send_json_error( 246 array( 247 'status' => - 1, 248 'message' => $msg, 249 ) 250 ); 251 } 252 * @codingStandardsIgnoreEnd 253 */ 257 254 258 255 // Get our settings … … 268 265 ) 269 266 ); 270 exit();271 267 } 272 268 … … 287 283 ) 288 284 ); 289 exit();290 285 } 291 286 … … 371 366 } 372 367 373 $buffered_text = ob_get_clean(); 368 $buffered_text = ob_get_clean(); 369 $display_errors = $this->variables->get( 'display_errors' ); 374 370 375 371 // No users imported (or done) … … 383 379 //Clear position 384 380 delete_option( "e20rcsv_{$file}" ); 385 $display_errors = $this->variables->get( 'display_errors' );386 381 387 382 // Delete the transient storing the file name … … 397 392 ) 398 393 ); 399 exit();400 394 401 395 } elseif ( ! empty( $results['errors'] ) ) { … … 425 419 ) 426 420 ); 427 exit();428 421 } else { 429 422 … … 462 455 ) 463 456 ); 464 exit();465 457 } 466 458 } -
pmpro-import-members-from-csv/trunk/src/import/class-csv.php
r2554806 r2563515 21 21 22 22 use E20R\Import_Members\Error_Log; 23 use E20R\Import_Members\Modules\Users\Column_Validation as User_Validation;24 23 use E20R\Import_Members\Modules\Users\Import_User; 25 24 use E20R\Import_Members\Status; … … 37 36 38 37 /** 39 * The CSV file (as a SplFileObject() class )40 *41 * @var SplFileObject $file_object42 */43 private $file_object;44 45 /**46 38 * Error log class 47 39 * @var Error_Log|null $error_log = null; … … 60 52 * @var null|CSV $csv 61 53 */ 62 private $csv = null;54 private $csv; 63 55 64 56 /** … … 201 193 } 202 194 195 // @phpstan-ignore-next-line 196 $this->error_log->debug( 'Directory error? ' . ( $directory_error ? 'Yes' : 'No' ) ); 197 $this->error_log->debug( 'File upload not selected error? ' . ( $no_file_error ? 'Yes' : 'No' ) ); 198 $this->error_log->debug( 'File limit error? ' . ( $clean_file_error ? 'Yes' : 'No' ) ); 199 200 // @phpstan-ignore-next-line 203 201 if ( ( true === $no_file_error || true === $directory_error || true === $clean_file_error ) ) { 204 205 202 $this->error_log->debug( 'Error: Problem with uploaded file...' ); 206 $this->error_log->debug( 'Directory error? ' . ( $directory_error ? 'Yes' : 'No' ) );207 $this->error_log->debug( 'File upload not selected error? ' . ( $no_file_error ? 'Yes' : 'No' ) );208 $this->error_log->debug( 'File limit error? ' . ( $clean_file_error ? 'Yes' : 'No' ) );209 210 203 return false; 211 204 } … … 333 326 334 327 // Mac CR+LF fix 335 ini_set( 'auto_detect_line_endings', true);328 ini_set( 'auto_detect_line_endings', '1' ); 336 329 337 330 $file = basename( $file_name ); … … 414 407 415 408 $this->error_log->debug( "Processing next user data. (previous line #: {$active_line_number})" ); 416 417 409 $this->extract_data( 418 410 $line, … … 493 485 $user_id = $import_user->import( $user_data, $user_meta, $headers ); 494 486 495 if ( false ===$user_ids ) {487 if ( ! $user_ids ) { 496 488 497 489 $msg = sprintf( … … 519 511 // Close the file (done by the destructor for the SplFileObject() class) 520 512 $file_object = null; 521 ini_set( 'auto_detect_line_endings', true);513 ini_set( 'auto_detect_line_endings', '1' ); 522 514 523 515 // One more thing to do after all imports? -
pmpro-import-members-from-csv/trunk/src/modules/BuddyPress/class-buddypress.php
r2554806 r2563515 72 72 * @access private 73 73 */ 74 p rivatefunction __construct() {74 public function __construct() { 75 75 $this->data = new Data(); 76 76 $this->error_log = new Error_Log(); // phpcs:ignore … … 84 84 ); 85 85 } 86 87 /**88 * Get or instantiate and return this class (BuddyPress)89 *90 * @return BuddyPress|null91 */92 // public static function get_instance() {93 // if ( null === self::$instance ) {94 // self::$instance = new self();95 // }96 // return self::$instance;97 // }98 86 99 87 /** … … 149 137 return $field_list + $this->field_list; 150 138 } 151 152 /**153 * Clone the class (Singleton)154 *155 * @access private156 */157 private function __clone() {158 // TODO: Implement __clone() method.159 }160 139 } -
pmpro-import-members-from-csv/trunk/src/modules/BuddyPress/class-column-validation.php
r2554806 r2563515 38 38 namespace E20R\Import_Members\Modules\BuddyPress; 39 39 40 41 40 use E20R\Import_Members\Error_Log; 42 41 use E20R\Import_Members\Validate\Base_Validation; 42 use E20R\Import_Members\Modules\BuddyPress\BuddyPress; 43 43 44 44 class Column_Validation extends Base_Validation { 45 45 46 46 /** 47 47 * Get or instantiate and get the current class 48 48 * 49 * @return Column_Validation| null49 * @return Column_Validation|Base_Validation|null 50 50 */ 51 51 public static function get_instance() { … … 53 53 if ( true === is_null( self::$instance ) ) { 54 54 self::$instance = new self(); 55 55 56 56 add_filter( 57 57 'e20r_import_errors_to_ignore', 58 58 array( self::$instance, 'load_ignored_module_errors' ), 59 59 10, 60 260 2 61 61 ); 62 62 63 63 // Add list of errors to ignore for the BuddyPress module 64 64 self::$instance->errors_to_ignore = apply_filters( … … 71 71 return self::$instance; 72 72 } 73 73 74 74 /** 75 75 * Define the module specific errors to ignore … … 81 81 */ 82 82 public function load_ignored_module_errors( $ignored_error_list, $module_name = 'buddypress' ) { 83 84 if ( $module_name !== 'buddypress') {83 84 if ( 'buddypress' !== $module_name ) { 85 85 return $ignored_error_list; 86 86 } 87 88 $this->error_log->debug( "Loading BuddyPress specific error(s) when it's safe to can continue importing");89 87 88 $this->error_log->debug( "Loading BuddyPress specific error(s) when it's safe to can continue importing" ); 89 90 90 $this->errors_to_ignore = array( 91 91 'bp_field_name' => true, 92 92 ); 93 93 94 94 return $ignored_error_list + $this->errors_to_ignore; 95 95 } 96 96 97 97 /** 98 98 * Load action and filter handlers for PMPro validation … … 103 103 return; 104 104 } 105 105 106 106 add_filter( 'e20r_import_members_validate_field_data', array( $this, 'bp_field_exists' ), 1, 3 ); 107 107 } … … 117 117 */ 118 118 public function bp_field_exists( $has_error, $user_id, $fields ) { 119 120 $buddy_press = BuddyPress::get_instance();119 120 $buddy_press = new BuddyPress(); 121 121 $buddy_press->load_fields( array() ); 122 122 123 if ( ! isset( $fields['bp_field_name'] )) {124 $this->error_log->debug( "No need to process 'bp_field_name' column");123 if ( ! isset( $fields['bp_field_name'] ) ) { 124 $this->error_log->debug( "No need to process 'bp_field_name' column" ); 125 125 return $has_error; 126 126 } 127 127 128 if ( ! isset( $fields['bp_field_name'] ) && in_array( 'bp_field_name', array_keys( $fields ) ) ) {128 if ( ! isset( $fields['bp_field_name'] ) && in_array( 'bp_field_name', array_keys( $fields ), true ) ) { 129 129 $this->error_log->debug( "'bp_field_name' is doesn't need to be processed..." ); 130 130 return $has_error; … … 132 132 133 133 if ( isset( $fields['bp_field_name'] ) && empty( $fields['bp_field_name'] ) ) { 134 $has_error = $has_error && ( true &&! $this->ignore_validation_error( 'bp_field_name' ) );134 $has_error = $has_error && ( ! $this->ignore_validation_error( 'bp_field_name' ) ); 135 135 } 136 136 137 137 // FIXME: Add check for 'bp_field_exists' for the supplied fields/data 138 138 139 139 return $has_error; 140 140 } 141 142 /**143 * Disable the __clone() magic method144 *145 * @access private146 */147 private function __clone() {148 // TODO: Implement __clone() method.149 }150 141 } -
pmpro-import-members-from-csv/trunk/src/modules/BuddyPress/class-import-buddypress.php
r2554806 r2563515 20 20 namespace E20R\Import_Members\Modules\BuddyPress; 21 21 22 23 22 class Import_BuddyPress { 24 23 // TODO: Create BuddyPress import class 25 24 } -
pmpro-import-members-from-csv/trunk/src/modules/PMPro/class-column-validation.php
r2554806 r2563515 32 32 * Instance of the PMPro Column_Validation class 33 33 * 34 * @var null|Column_Validation $instance34 * @var null|Column_Validation|Base_Validation $instance 35 35 */ 36 36 protected static $instance = null; … … 39 39 * Get or instantiate and get the current class 40 40 * 41 * @return Column_Validation| null42 */ 43 public static function get_instance() : \E20R\Import_Members\Modules\PMPro\Column_Validation{41 * @return Column_Validation|Base_Validation|null 42 */ 43 public static function get_instance() { 44 44 45 45 if ( true === is_null( self::$instance ) ) { … … 165 165 $e20r_import_err['invalid_membership_id'] = new WP_Error( 'e20r_im_member', $msg ); 166 166 167 $has_error = true &&( ! $this->ignore_validation_error( 'invalid_membership_id' ) );167 $has_error = ( ! $this->ignore_validation_error( 'invalid_membership_id' ) ); 168 168 169 169 return $has_error; … … 173 173 * Can't import membership data when user has incorrect start date format 174 174 * 175 * @param $has_error176 * @param $user_id177 * @param $fields175 * @param bool $has_error 176 * @param int $user_id 177 * @param array $fields 178 178 * 179 179 * @return bool … … 228 228 ); 229 229 230 $has_error = true &&( ! $this->ignore_validation_error( 'startdate_format' ) );230 $has_error = ( ! $this->ignore_validation_error( 'startdate_format' ) ); 231 231 } 232 232 … … 237 237 * Can't import membership data when user has incorrect start date format or value 238 238 * 239 * @param $has_error240 * @param $user_id241 * @param $fields239 * @param bool $has_error 240 * @param int $user_id 241 * @param array $fields 242 242 * 243 243 * @return bool … … 289 289 290 290 $e20r_import_err['no_startdate'] = new WP_Error( 'e20r_im_member', $msg ); 291 $has_error = true &&( ! $this->ignore_validation_error( 'no_startdate' ) );291 $has_error = ( ! $this->ignore_validation_error( 'no_startdate' ) ); 292 292 } 293 293 return $has_error; … … 297 297 * Possible problem for membership data when user has incorrect end date format or value 298 298 * 299 * @param $has_error300 * @param $user_id301 * @param $fields299 * @param bool $has_error 300 * @param int $user_id 301 * @param array $fields 302 302 * 303 303 * @return bool … … 335 335 336 336 $e20r_import_err['bad_format_enddate'] = new WP_Error( 'e20r_im_member', $msg ); 337 $has_error = true &&( ! $this->ignore_validation_error( 'bad_format_enddate' ) );337 $has_error = ( ! $this->ignore_validation_error( 'bad_format_enddate' ) ); 338 338 339 339 $should_be = Time::convert( $fields['membership_enddate'] ); … … 378 378 if ( 379 379 ! empty( $fields['membership_enddate'] ) && 380 isset( $fields['membership_status'] ) && 'inactive' === $fields['membership_status'] && 380 ! empty( $fields['membership_status'] ) && 381 'inactive' === $fields['membership_status'] && 381 382 ( time() < strtotime( $fields['membership_enddate'], time() ) ) 382 383 ) { … … 395 396 396 397 $e20r_import_err['inactive_and_enddate'] = new WP_Error( 'e20r_im_member', $msg ); 397 $has_error = true &&( ! $this->ignore_validation_error( 'inactive_and_enddate' ) );398 $has_error = ( ! $this->ignore_validation_error( 'inactive_and_enddate' ) ); 398 399 } 399 400 … … 450 451 451 452 $e20r_import_err['valid_status'] = new WP_Error( 'e20r_im_member', $msg ); 452 $has_error = true &&( ! $this->ignore_validation_error( 'valid_status' ) );453 $has_error = ( ! $this->ignore_validation_error( 'valid_status' ) ); 453 454 } 454 455 … … 505 506 506 507 $e20r_import_err['link_subscription'] = new WP_Error( 'e20r_im_member', $msg ); 507 $has_error = true &&( ! $this->ignore_validation_error( 'link_subscription' ) );508 $has_error = ( ! $this->ignore_validation_error( 'link_subscription' ) ); 508 509 } 509 510 … … 552 553 553 554 $e20r_import_err['invalid_recurring_config'] = new WP_Error( 'e20r_im_member', $msg ); 554 $has_error = true &&( ! $this->ignore_validation_error( 'invalid_recurring_config' ) );555 $has_error = ( ! $this->ignore_validation_error( 'invalid_recurring_config' ) ); 555 556 } 556 557 … … 594 595 ); 595 596 $e20r_import_err['sub_id_no_paym_id'] = new WP_Error( 'e20r_im_member', $msg ); 597 $has_error = ( ! $this->ignore_validation_error( 'sub_id_no_paym_id' ) ); 596 598 } 597 599 … … 674 676 $e20r_import_err[ "no_membership_id_column_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 675 677 676 $has_error = true &&( ! $this->ignore_validation_error( 'no_membership_id_column' ) );678 $has_error = ( ! $this->ignore_validation_error( 'no_membership_id_column' ) ); 677 679 } 678 680 … … 690 692 $e20r_import_err[ "no_membership_id_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 691 693 692 $has_error = true &&( ! $this->ignore_validation_error( 'no_membership_id' ) );694 $has_error = ( ! $this->ignore_validation_error( 'no_membership_id' ) ); 693 695 } 694 696 … … 707 709 $e20r_import_err[ "cancelling_membership_level_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 708 710 709 $has_error = false;711 $has_error = ( ! $this->ignore_validation_error( 'cancelling_membership_level' ) ); 710 712 } 711 713 … … 752 754 $e20r_import_err[ "level_exists_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 753 755 754 $has_error = true &&( ! $this->ignore_validation_error( 'level_exists' ) );756 $has_error = ( ! $this->ignore_validation_error( 'level_exists' ) ); 755 757 } 756 758 return $has_error; … … 799 801 $e20r_import_err[ "recurring_w_enddate_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 800 802 801 $has_error = true &&( ! $this->ignore_validation_error( 'recurring_w_enddate' ) );803 $has_error = ( ! $this->ignore_validation_error( 'recurring_w_enddate' ) ); 802 804 } 803 805 return $has_error; … … 845 847 $e20r_import_err[ "correct_gw_env_variable_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 846 848 847 $has_error = true &&( ! $this->ignore_validation_error( 'correct_gw_env_variable' ) );849 $has_error = ( ! $this->ignore_validation_error( 'correct_gw_env_variable' ) ); 848 850 } 849 851 … … 893 895 $e20r_import_err[ "supported_gateway_{$active_line_number}" ] = new WP_Error( 'e20r_im_member', $msg ); 894 896 895 $has_error = true &&( ! $this->ignore_validation_error( 'supported_gateway' ) );897 $has_error = ( ! $this->ignore_validation_error( 'supported_gateway' ) ); 896 898 } 897 899 } -
pmpro-import-members-from-csv/trunk/src/modules/PMPro/class-import-member.php
r2554806 r2563515 176 176 $has_error = false; 177 177 $membership_in_the_past = false; 178 179 // Define table names 180 $pmpro_member_table = "{$wpdb->prefix}pmpro_memberships_users"; 181 $pmpro_dc_table = "{$wpdb->prefix}pmpro_discount_codes"; 182 183 $current_blog_id = get_current_blog_id(); 178 $current_blog_id = get_current_blog_id(); 184 179 185 180 $this->error_log->debug( "Current blog ID: {$current_blog_id}" ); … … 266 261 $wpdb->prepare( 267 262 "SELECT dc.id 268 FROM {$ pmpro_dc_table}AS dc263 FROM {$wpdb->prefix}pmpro_discount_codes AS dc 269 264 WHERE dc.code = %s 270 265 LIMIT 1", … … 291 286 // Update all currently active memberships with the specified ID for the specified user 292 287 $updated = $wpdb->update( 293 $pmpro_member_table,288 "{$wpdb->prefix}pmpro_memberships_users", 294 289 array( 'status' => 'admin_cancelled' ), 295 290 array( … … 392 387 $wpdb->prepare( 393 388 "SELECT mt.id 394 FROM {$ pmpro_member_table}AS mt389 FROM {$wpdb->prefix}pmpro_memberships_users AS mt 395 390 WHERE mt.user_id = %d AND mt.membership_id = %d AND mt.status = %s 396 391 ORDER BY mt.id DESC LIMIT 1", … … 404 399 $wpdb->prepare( 405 400 "SELECT mt.id 406 FROM {$ pmpro_member_table}AS mt401 FROM {$wpdb->prefix}pmpro_memberships_users AS mt 407 402 WHERE mt.user_id = %d AND mt.membership_id = %d 408 403 ORDER BY mt.id DESC LIMIT 1", … … 430 425 431 426 if ( false !== $wpdb->update( 432 $pmpro_member_table,427 "{$wpdb->prefix}pmpro_memberships_users", 433 428 array( 434 429 'status' => 'inactive', … … 469 464 470 465 if ( false === $wpdb->update( 471 $pmpro_member_table,466 "{$wpdb->prefix}pmpro_memberships_users", 472 467 array( 473 468 'status' => 'active', … … 515 510 516 511 // Update the error status 517 if ( true === $has_error ) { 518 update_option( 'e20r_import_errors', $has_error ); 519 } 512 update_option( 'e20r_import_errors', $has_error ); 520 513 521 514 if ( is_multisite() ) { … … 592 585 } 593 586 594 $order = new \MemberOrder(); 595 $order->user_id = $user_id; 596 $order->membership_id = isset( $record['membership_id'] ) ?? $record['membership_id']; 597 $order->InitialPayment = ! empty( $record['membership_initial_payment'] ) ? $record['membership_initial_payment'] : null; 587 $order = new \MemberOrder(); 588 $order->user_id = $user_id; // @phpstan-ignore-line 589 $order->membership_id = isset( $record['membership_id'] ) ?? $record['membership_id']; // @phpstan-ignore-line 590 591 // phpcs:ignore 592 $order->InitialPayment = ! empty( $record['membership_initial_payment'] ) ? $record['membership_initial_payment'] : null; // @phpstan-ignore-line 598 593 599 594 /** … … 616 611 617 612 if ( ! isset( $order->billing ) ) { 618 $order->billing = new \stdClass(); 613 $order->billing = new \stdClass(); // @phpstan-ignore-line 619 614 } 620 615 … … 635 630 if ( 'total' === $field_name && ! empty( $record['membership_initial_payment'] ) ) { 636 631 637 $order->total = $record['membership_initial_payment']; 632 $order->total = $record['membership_initial_payment']; // @phpstan-ignore-line 638 633 639 634 } elseif ( 'total' === $field_name && ( … … 642 637 ) ) { 643 638 644 $order->total = $record['membership_billing_amount']; 639 $order->total = $record['membership_billing_amount']; // @phpstan-ignore-line 645 640 646 641 } elseif ( 'total' !== $field_name ) { 647 642 648 643 if ( 'status' === $field_name ) { 644 // @phpstan-ignore-next-line 649 645 $order->{$field_name} = ( isset( $record[ $full_field_name ] ) && 'active' === $record[ $full_field_name ] ? 'success' : 'cancelled' ); 650 646 } else { … … 663 659 664 660 if ( isset( $record['membership_gateway_environment'] ) && strtolower( $default_environment ) !== strtolower( $record['membership_gateway_environment'] ) ) { 665 $order->gateway_environment = strtolower( $record['membership_gateway_environment'] ); 661 $order->gateway_environment = strtolower( $record['membership_gateway_environment'] ); // @phpstan-ignore-line 666 662 } 667 663 668 664 if ( true === $membership_in_the_past ) { 669 $order->status = 'cancelled'; 665 $order->status = 'cancelled'; // @phpstan-ignore-line 670 666 } 671 667 -
pmpro-import-members-from-csv/trunk/src/modules/PMPro/class-import-sponsors.php
r2554806 r2563515 74 74 */ 75 75 public function load_sponsor_import() { 76 if ( true === Licensing::is_licensed( 'import_sponsors' ) ) { 76 $check = new \ReflectionMethod( 'E20R\Utilities\Licensing\Licensing', '__construct' ); 77 78 if ( false === $check->isPrivate() ) { 79 $licensing = new Licensing( Import_Members::E20R_LICENSE_SKU ); 80 $is_licensed = $licensing->is_licensed( Import_Members::E20R_LICENSE_SKU, false ); 81 } else { 82 // @phpstan-ignore-next-line 83 $is_licensed = Licensing::is_licensed( Import_Members::E20R_LICENSE_SKU, false ); 84 } 85 86 if ( true === $is_licensed ) { 77 87 add_action( 'e20r_after_user_import', array( $this, 'maybe_add_sponsor_info' ), 100, 3 ); 78 88 } … … 169 179 * 170 180 * @param int $sponsored_user_id 171 * @param Sponsor $sponsor181 * @param Sponsor|\WP_User $sponsor 172 182 * @param bool $last_try 173 183 * … … 196 206 197 207 // Get user info and ensure they have a current membership level 198 $sponsored_user = get_userdata( $sponsored_user_id ); 208 $sponsored_user = get_userdata( $sponsored_user_id ); 209 210 // @phpstan-ignore-next-line 199 211 $sponsored_user->membership_level = pmpro_getMembershipLevelForUser( $sponsored_user_id, true ); 200 212 $delayed_sponsor_link = $this->variables->get( 'delayed_sponsor_link' ); … … 235 247 236 248 //Make sure the sponsor has a discount code 237 $code_id = pmprosm_getCodeByUserID( $sponsor_id ); 249 $code_id = pmprosm_getCodeByUserID( $sponsor_id ); // @phpstan-ignore-line 238 250 239 251 $this->error_log->debug( "Got sponsor code {$code_id} for sponsor {$sponsor_id}" ); … … 295 307 $this->error_log->debug( "Have to create a sponsor code for {$sponsor_id}" ); 296 308 309 // @phpstan-ignore-next-line 297 310 $code_id = pmprosm_createSponsorCode( $sponsor_id, $sponsor_level_id, $uses ); 298 311 } … … 317 330 'code_id' => $code_id, 318 331 'user_id' => $sponsored_user_id, 319 'membership_id' => $sponsored_user->membership_level->id, 332 'membership_id' => $sponsored_user->membership_level->id, // @phpstan-ignore-line 320 333 'status' => 'active', 321 334 ); … … 342 355 $this->error_log->debug( "Updated member record for {$sponsored_user_id} with sponsor info" ); 343 356 357 // @phpstan-ignore-next-line 344 358 pmprosm_addDiscountCodeUse( $sponsored_user_id, $sponsored_user->membership_level->ID, $code_id ); 345 359 346 360 $this->error_log->debug( "Updated the usage of {$code_id}" ); 347 361 348 if ( empty( $e rror ) ) {362 if ( empty( $e20r_import_err ) ) { 349 363 $status = true; 350 364 … … 353 367 354 368 } else { 355 $ error->log_errors(356 array( $error ),369 $this->error_log->log_errors( 370 $e20r_import_err, 357 371 $this->variables->get( 'log_file_path' ), 358 372 $this->variables->get( 'log_file_url' ) … … 398 412 } 399 413 414 // @phpstan-ignore-next-line 400 415 $sponsor->membership_level = pmpro_getMembershipLevelForUser( $sponsor_id, true ); 401 416 -
pmpro-import-members-from-csv/trunk/src/modules/PMPro/class-pmpro.php
r2554806 r2563515 18 18 */ 19 19 namespace E20R\Import_Members\Modules\PMPro; 20 21 20 22 21 use E20R\Import_Members\Error_Log; -
pmpro-import-members-from-csv/trunk/src/modules/PMPro/class-sponsor.php
r2554806 r2563515 20 20 namespace E20R\Import_Members\Modules\PMPro; 21 21 22 23 22 use E20R\Import_Members\Data; 24 23 25 24 class Sponsor { 26 25 27 26 /** 28 27 * The sponsor's WP_User ID … … 31 30 */ 32 31 private $ID = null; 33 32 34 33 /** 35 34 * User Record for the sponsor … … 38 37 */ 39 38 private $user = null; 40 39 41 40 /** 42 41 * The membership level information for the sponsor … … 45 44 */ 46 45 private $membership_level = null; 47 46 48 47 /** 49 48 * Sponsor constructor. 50 49 * 51 * @param $user_id50 * @param int|string $user_id 52 51 * 53 52 * @throws \Exception 54 53 */ 55 54 public function __construct( $user_id = null ) { 56 57 $data = Data::get_instance();58 55 56 $data = new Data(); 57 59 58 if ( ! empty( $user_id ) ) { 60 59 $this->user = $data->get_user_info( $user_id ); 61 60 } 62 63 if ( !empty( $user_id ) && empty( $this->user ) ) { 64 throw new \Exception( sprintf( __( 'No user with that ID (%s) found!', 'pmpro-import-members-from-csv' ), $user_id ) ); 61 62 if ( ! empty( $user_id ) && empty( $this->user ) ) { 63 throw new \Exception( 64 sprintf( 65 // translators: %s - Supplied User ID, email or login name 66 __( 'No user with that ID (%s) found!', 'pmpro-import-members-from-csv' ), 67 $user_id 68 ) 69 ); 65 70 } 66 71 } 67 72 68 73 /** 69 74 * Set Sponsor parameter by type … … 76 81 */ 77 82 public function set( $param, $value, $type = null ) { 78 83 79 84 $attributes = get_class_vars( __CLASS__ ); 80 81 if ( ! in_array( $param, $attributes ) && ! in_array( $type, $attributes) ) {85 86 if ( ! in_array( $param, $attributes, true ) && ! in_array( $type, $attributes, true ) ) { 82 87 return false; 83 88 } 84 89 85 90 switch ( $type ) { 86 91 87 92 case 'user': 88 93 if ( isset( $this->user->{$param} ) ) { … … 92 97 } 93 98 break; 94 99 95 100 case 'membership': 96 97 101 if ( isset( $this->membership_level->{$param} ) ) { 98 102 $this->membership_level->{$param} = $value; … … 101 105 } 102 106 break; 103 107 104 108 default: 105 109 $this->{$param} = $value; 106 110 } 107 111 108 112 return true; 109 113 } 110 114 111 115 /** 112 116 * Return the type specific parameter (membership info, user info, class variable) 113 117 * 114 * @param string $type118 * @param string|null $type 115 119 * @param string $param 116 120 * … … 118 122 */ 119 123 public function get( $type, $param ) { 120 124 121 125 $attributes = get_class_vars( __CLASS__ ); 122 126 $value = null; 123 124 if ( ! in_array( $param, $attributes ) ) {127 128 if ( ! in_array( $param, $attributes, true ) ) { 125 129 return false; 126 130 } 127 131 128 132 switch ( $type ) { 129 133 130 134 case 'user': 131 135 $value = $this->user->{$param}; 132 136 break; 133 137 134 138 case 'membership': 135 136 139 $value = $this->membership_level->{$param}; 137 140 break; 138 141 139 142 default: 140 143 $value = $this->{$param}; 141 144 } 142 145 143 146 return $value; 144 147 } -
pmpro-import-members-from-csv/trunk/src/modules/Users/class-column-validation.php
r2554806 r2563515 36 36 * Get or instantiate and get the current class 37 37 * 38 * @return Column_Validation| null38 * @return Column_Validation|Base_Validation|null 39 39 */ 40 40 public static function get_instance() { … … 134 134 * @param null|string|string[] $field_name 135 135 * 136 * @return bool|int |false136 * @return bool|int 137 137 */ 138 138 public function validate_user_id( $has_error, $user_id, $record, $field_name = null ) { … … 147 147 $this->error_log->debug( 'Cannot find one of the expected column(s): ID, user_email, user_login' ); 148 148 return $has_error; 149 }150 151 if ( is_array( $field_name ) ) {152 // TODO: Process list of fields153 149 } 154 150 … … 190 186 return true; 191 187 } 192 193 /**194 * Disable the __clone() magic method195 *196 * @access private197 */198 private function __clone() {199 // TODO: Implement __clone() method.200 }201 188 } -
pmpro-import-members-from-csv/trunk/src/modules/Users/class-import-user.php
r2554806 r2563515 353 353 } else { 354 354 $update = false; 355 $id = null; 355 356 // Here we're supposed to hash the password 356 357 // $user_pass = wp_hash_password( $userdata['user_pass'] ); … … 555 556 556 557 if ( true === $update ) { 557 $wpdb->update( $wpdb->users, $data, compact( ' ID' ) );558 $wpdb->update( $wpdb->users, $data, compact( 'id' ) ); 558 559 $user_id = (int) $id; 559 560 } else { -
pmpro-import-members-from-csv/trunk/src/modules/Users/class-user-validation.php
r2554806 r2563515 20 20 namespace E20R\Import_Members\Validate; 21 21 22 23 22 use E20R\Import_Members\Import_Members; 24 23 use E20R\Import_Members\Status; 25 24 26 25 class User_Validation extends Validate { 27 28 26 27 /** 28 * Return the User_Validation class instance 29 * 30 * @return Base_Validation|User_Validation|null 31 */ 32 public static function get_instance() { 33 if ( null === self::$instance ) { 34 self::$instance = new self(); 35 } 36 37 return self::$instance; 38 } 39 40 /** 41 * Return list of validation errors we'll ignore (only warn for) 42 * 43 * @param array $ignored_error_list 44 * @param string $module_name 45 * 46 * @return array 47 */ 48 public function load_ignored_module_errors( $ignored_error_list, $module_name = 'users' ) { 49 return $ignored_error_list; 50 } 51 52 /** 53 * Load action and filter handlers for PMPro validation 54 */ 55 public function load_actions() { 56 57 add_filter( 58 'e20r_import_users_validate_field_data', 59 array( $this, 'validate' ), 60 1, 61 3 62 ); 63 } 64 29 65 /** 30 66 * Process the status for user validations and set a status message … … 36 72 */ 37 73 public static function status_msg( $status, $allow_update ) { 38 74 39 75 global $e20r_import_err; 40 76 global $active_line_number; 41 77 42 78 $should_exit = false; 43 79 … … 51 87 52 88 case Status::E20R_ERROR_UPDATE_NEEDED_NOT_ALLOWED: 53 $msg = __(89 $msg = __( 54 90 'User ID specified and user record exists but the "Update User Record" option is not selected', 55 91 'pmpro-import-members-from-csv' … … 67 103 break; 68 104 default: 69 70 $msg = null; 105 $msg = null; 71 106 $should_exit = false; 72 107 } 73 108 74 109 // Process the resulting error/warning message 75 110 if ( ! empty( $msg ) ) { 76 111 77 112 // Save the error message (based on the supplied status) 78 $e20r_import_err[ "user_check_{$active_line_number}"] = $msg;79 113 $e20r_import_err[ "user_check_{$active_line_number}" ] = $msg; 114 80 115 return $should_exit; 81 116 } 82 117 83 118 return false; 84 119 } 85 120 86 121 /** 87 122 * Validate the User information in the record … … 93 128 */ 94 129 public static function validate( $record, $allow_update ) { 95 96 return false; 130 131 // TODO: Implement validation logic for User record(s) 132 return ! empty( $record ); 97 133 } 98 134 } -
pmpro-import-members-from-csv/trunk/src/validate/class-base-validation.php
r2554806 r2563515 23 23 24 24 use E20R\Import_Members\Error_Log; 25 use E20R\Import_Members\Modules\PMPro\Column_Validation as PMPro_Validation; 26 use E20R\Import_Members\Modules\Users\Column_Validation as User_Validation; 27 use E20R\Import_Members\Modules\BuddyPress\Column_Validation as BP_Validation; 25 28 26 29 abstract class Base_Validation { … … 29 32 * Instance of the column validation logic for PMPro 30 33 * 31 * @var null|Base_Validation 34 * @var null|Base_Validation|PMPro_Validation|User_Validation|BP_Validation 32 35 */ 33 36 protected static $instance = null; … … 75 78 * Get or instantiate and get the current class 76 79 * 77 * @return Column_Validation|Base_Validation|null80 * @return User_Validation|PMPro_Validation|BP_Validation|Base_Validation|null 78 81 */ 79 82 abstract public static function get_instance(); … … 81 84 /** 82 85 * Load all validation actions for the specific module 83 *84 * @return null85 86 */ 86 87 abstract public function load_actions(); -
pmpro-import-members-from-csv/trunk/src/validate/class-date-format.php
r2554806 r2563515 21 21 22 22 class Date_Format { 23 23 24 24 /** 25 25 * Test the date supplied for MySQL compliance … … 33 33 */ 34 34 public static function validate( $date, $format ) { 35 35 36 36 $check_date = \DateTime::createFromFormat( $format, $date ); 37 $retval = ( false !== $check_date ) && ( $check_date->format( $format ) == $date ); 38 39 return $retval; 37 38 return ( false !== $check_date ) && ( $check_date->format( $format ) === $date ); 40 39 } 41 40 42 41 }
Note: See TracChangeset
for help on using the changeset viewer.