├── .editorconfig ├── .gitignore ├── MarketCheck.php ├── README.md ├── composer.json ├── img └── find-item-purchase-code.png ├── includes └── MarketCheck │ ├── Database.php │ ├── Markets │ ├── Envato │ │ ├── QueryMarket.php │ │ └── Settings.php │ ├── Mojo │ │ ├── QueryMarket.php │ │ └── Settings.php │ └── QueryMarket.php │ ├── Settings.php │ ├── Settings │ ├── Fields.php │ └── MarketSettings.php │ ├── Setup │ └── Setup.php │ ├── SignUp.php │ └── UserManagement.php ├── lang └── dummy.mo ├── register-custom-markets.php └── vendor ├── autoload.php └── composer ├── ClassLoader.php ├── autoload_classmap.php ├── autoload_namespaces.php ├── autoload_psr4.php └── autoload_real.php /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | insert_final_newline = false 10 | trim_trailing_whitespace = true 11 | indent_style = tab 12 | 13 | [{.jshintrc,*.json,*.yml}] 14 | indent_style = space 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.sublime-* 2 | -------------------------------------------------------------------------------- /MarketCheck.php: -------------------------------------------------------------------------------- 1 | install(); 53 | update_option( "marketcheck_version", MARKETCHECK_DB_VERSION ); 54 | } 55 | 56 | do_action( "marketcheck/register-market", $fields, $settings->getSettings(), $registerForm, $db ); 57 | } 58 | } 59 | new MarketCheck; 60 | 61 | if( file_exists( dirname( __FILE__ ) . '/register-custom-markets.php' ) ) { 62 | include( dirname( __FILE__ ) . '/register-custom-markets.php' ); 63 | } 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## MarketCheck 2 | * Author: Ionuț Staicu 3 | * Author URI: [ionutstaicu.com](http://ionutstaicu.com) 4 | * Inspired by Aqua Verifier by Syamil MJ 5 | 6 | ### Overview 7 | 8 | MarketCheck is a simple WordPress plugin that modifies the default user registration page by adding a verification form using various markets. E.g. Envato, Mojo and so on (basically any market that provides an API to check a purchase). 9 | 10 | Coupled with BBPress plugin, this will allow you to easily create your own Support Forum while still having all the default functionalities of the registration form that everyone is already familiar with. 11 | 12 | ### Server requirements 13 | Because we make good use of PHP namespaces, your server should support at least PHP 5.3, but any newer version would work just fine. 14 | 15 | ### License 16 | 17 | MarketCheck is released under GPLv3 - [http://www.gnu.org/copyleft/gpl.html](http://www.gnu.org/copyleft/gpl.html). You are free to redistribute & modify the plugin in either free or commercial products. Please kindly keep all links & credits intact. 18 | 19 | #### A small note about Aqua Verifier 20 | Although this was initially a fork of Aqua Verifier, I ended up by rewriting almost every piece of code in order to suit my needs. 21 | 22 | Here are the main differences between Aqua Verifier and MarketCheck 23 | 24 | - it's extensible; If you have products on multiple markets, you can add as many markets as you like; 25 | - it requires PHP 5.3+ (although I tested only on 5.5 it should work with lower versions as well; 26 | - it has some hooks that allows you to... well, hook on user registration success; 27 | - it stores purchases info into a separate DB; 28 | - it doesn't really integrate with anything (so no role sets, no nothing). But since you have hooks, you can extend it in no time to integrate with bbpress or whatever; 29 | - it doesn't have an uninstall routine. Removing the plugin will NOT clear the DB or anything. 30 | 31 | I'm also planning to add some extra stuff like: 32 | 33 | key management (a registered user to be able to add and maybe delete more purchase keys) 34 | 35 | - a badge system (some methods to show a badge on forums); 36 | - an uninstall/reset routine to clear the db if needed; 37 | - a granular permission (e.g. access only certain forums) etc 38 | 39 | ### User Guide 40 | 41 | 1. Download & unzip to `wp-content/plugins` 42 | 2. Go to **Settings > General** and make the checkbox for `Anyone can register` is checked 43 | 3. Go to **Settings > MarketCheck** and fill in all the required fields 44 | 45 | ### Extensibility guide 46 | In order to add a new market, you need to follow three simple..ish steps: 47 | 48 | 1. Implement `QueryMarket` methods (for getting the URL and normalizing return values) 49 | 2. Implement `MarketSettings` methods (for registering new settings fields) 50 | 3. Register the new market (inside of `register-custom-markets.php` file): 51 | 52 | ``` 53 | add_action( 'marketcheck/register-market', function( $fields, $settings, $registerForm, $db ){ 54 | new Envato\Settings(); 55 | $registerForm->addMarket( new Envato\QueryMarket( $settings, $db ) ); 56 | }, 10, 4 ); 57 | 58 | ``` 59 | 60 | (you can take a look inside of `includes/MarketCheck/Markets` folder in order to see how we added first market) 61 | 62 | ### Bugs, Issues, Feedbacks, Help? 63 | 64 | Please report any bugs, issues, feedbacks or get help on the MarketCheck's Issues page on Github - [Issues page](https://github.com/iamntz/MarketCheck/issues). -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": {}, 3 | 4 | "autoload": { 5 | "psr-0": { 6 | "MarketCheck\\": "includes/" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /img/find-item-purchase-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iamntz/MarketCheck/c5f6b91765773cdb7b16bdfc6065940701f0ff6d/img/find-item-purchase-code.png -------------------------------------------------------------------------------- /includes/MarketCheck/Database.php: -------------------------------------------------------------------------------- 1 | dbName = $dbName; 12 | } 13 | 14 | 15 | public function wpdb() 16 | { 17 | if( !$this->wpdb ){ 18 | global $wpdb; 19 | $this->wpdb = $wpdb; 20 | } 21 | 22 | return $this->wpdb; 23 | } 24 | 25 | 26 | public function getDbName() 27 | { 28 | return $this->wpdb()->prefix . $this->dbName; 29 | } 30 | } -------------------------------------------------------------------------------- /includes/MarketCheck/Markets/Envato/QueryMarket.php: -------------------------------------------------------------------------------- 1 | settings['envato_user'], 11 | $this->settings['envato_api_key'], 12 | 'verify-purchase:' . $this->purchaseKey . '.json' 13 | ); 14 | 15 | return implode( '/', $apiURL ); 16 | } 17 | 18 | 19 | public function parsePurchase( $response ) 20 | { 21 | if( isset( $response['verify-purchase']['item_id'] ) ){ 22 | $parsedResponse = $response['verify-purchase']; 23 | 24 | return array( 25 | 'id' => $parsedResponse['item_id'], 26 | 'name' => $parsedResponse['item_name'], 27 | 'purchased_at' => $parsedResponse['created_at'], 28 | 'order_id' => $this->purchaseKey, 29 | 'market_name' => $this->getMarketName() 30 | ); 31 | } 32 | 33 | return null; 34 | } 35 | 36 | 37 | public function getHelp() 38 | { 39 | return 'You can find your item purchase code in your Envato user account » Downloads section'; 40 | } 41 | 42 | 43 | public function getMarketName() 44 | { 45 | return "Envato"; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /includes/MarketCheck/Markets/Envato/Settings.php: -------------------------------------------------------------------------------- 1 | addSection( 'Envato Market', 'envato_settings', $namespace ); 9 | 10 | $fields->addTextInput( array( 11 | "id" => 'envato_user', 12 | "title" => __( 'Envato API Owner', 'marketcheck' ), 13 | "section_id" => 'envato_settings', 14 | "namespace" => $namespace, 15 | "settings" => $settings, 16 | "desc" => __( 'Your Envato Username. WARNING! Your name is case sensitive!', 'marketcheck' ) 17 | ) ); 18 | 19 | $fields->addTextInput( array( 20 | "id" => 'envato_api_key', 21 | "title" => __( 'Envato API Key', 'marketcheck' ), 22 | "section_id" => 'envato_settings', 23 | "namespace" => $namespace, 24 | "settings" => $settings, 25 | "desc" => __( 'You can find this in your Envato user account under API Keys menu entry.', 'marketcheck' ) 26 | ) ); 27 | } 28 | } -------------------------------------------------------------------------------- /includes/MarketCheck/Markets/Mojo/QueryMarket.php: -------------------------------------------------------------------------------- 1 | settings['mojo_user'], 11 | $this->settings['mojo_api_key'], 12 | 'verify-purchase/' . $this->purchaseKey . '.json' 13 | ); 14 | 15 | return implode( '/', $apiURL ); 16 | } 17 | 18 | 19 | public function parsePurchase( $response ) 20 | { 21 | if( isset( $response['verify-purchase']['item_id'] ) ){ 22 | $parsedResponse = $response['verify-purchase']; 23 | 24 | return array( 25 | 'id' => $parsedResponse['item_id'], 26 | 'name' => $parsedResponse['name'], 27 | 'purchased_at' => $parsedResponse['purchase_date'], 28 | 'order_id' => $this->purchaseKey, 29 | 'market_name' => $this->getMarketName() 30 | ); 31 | } 32 | 33 | return null; 34 | } 35 | 36 | 37 | public function getHelp() 38 | { 39 | return 'You can find your item purchase code in your Mojo Marketplace user account » Downloads section'; 40 | } 41 | 42 | 43 | public function getMarketName() 44 | { 45 | return "Mojo Marketplace"; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /includes/MarketCheck/Markets/Mojo/Settings.php: -------------------------------------------------------------------------------- 1 | addSection( 'Mojo Market', 'mojo_settings', $namespace ); 9 | 10 | $fields->addTextInput( array( 11 | "id" => 'mojo_user', 12 | "title" => __( 'Mojo API Owner', 'marketcheck' ), 13 | "section_id" => 'mojo_settings', 14 | "namespace" => $namespace, 15 | "settings" => $settings, 16 | "desc" => __( 'Your Mojo Username. WARNING! Your name is case sensitive!', 'marketcheck' ) 17 | ) ); 18 | 19 | $fields->addTextInput( array( 20 | "id" => 'mojo_api_key', 21 | "title" => __( 'Mojo API Key', 'marketcheck' ), 22 | "section_id" => 'mojo_settings', 23 | "namespace" => $namespace, 24 | "settings" => $settings, 25 | "desc" => __( 'You can find this in your Mojo user account under API Keys menu entry.', 'marketcheck' ) 26 | ) ); 27 | } 28 | } -------------------------------------------------------------------------------- /includes/MarketCheck/Markets/QueryMarket.php: -------------------------------------------------------------------------------- 1 | settings = $settings; 13 | $this->db = $db; 14 | } 15 | 16 | 17 | public function setPurchaseKey( $purchaseKey ) 18 | { 19 | $this->purchaseKey = $purchaseKey; 20 | } 21 | 22 | 23 | protected function retreiveApi() 24 | { 25 | $apiUrl = $this->getApiURL(); 26 | $response = wp_remote_get( $apiUrl ); 27 | 28 | if ( is_wp_error( $response ) ) { 29 | return null; 30 | } 31 | 32 | $body = wp_remote_retrieve_body( $response ); 33 | 34 | if( is_wp_error( $body ) ){ 35 | return null; 36 | } 37 | 38 | return json_decode( $body, true ); 39 | } 40 | 41 | 42 | public function getProduct() 43 | { 44 | return $this->parsePurchase( $this->retreiveApi() ); 45 | } 46 | 47 | 48 | public function isValidPurchase() 49 | { 50 | $parsedPurchase = $this->parsePurchase( $this->retreiveApi() ); 51 | $errors = new \WP_Error; 52 | 53 | if( !$parsedPurchase ){ 54 | $errors->add( 'invalid_purchase_key', __( 'Error: Invalid Purchase Key.', 'marketcheck' ) ); 55 | return $errors; 56 | } 57 | 58 | if( $this->isUniqueLicense() ){ 59 | return true; 60 | } else { 61 | $errors->add( 'purchase_key_already_used', __( 'Error: License is already used by another user.', 'marketcheck') ); 62 | return $errors; 63 | } 64 | } 65 | 66 | 67 | protected function isUniqueLicense() 68 | { 69 | $wpdb = $this->db->wpdb(); 70 | $dbName = $this->db->getDbName(); 71 | $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$dbName} WHERE order_id = %s", $this->purchaseKey ) ); 72 | 73 | return $count == 0; 74 | } 75 | 76 | 77 | /** 78 | * Get normalized API URL for each market 79 | * 80 | * @method getApiURL 81 | * 82 | * @return string API URL 83 | */ 84 | abstract public function getApiURL(); 85 | 86 | 87 | /** 88 | * Normalize purchases response 89 | * 90 | * @method parsePurchase 91 | * 92 | * @param array $response the response from the server 93 | * 94 | * @return mixed array of normalized items or null if fails 95 | */ 96 | abstract public function parsePurchase( $response ); 97 | 98 | 99 | /** 100 | * Get a help text to be displayed on the register form field 101 | * 102 | * @method getHelp 103 | * 104 | * @return string the help text 105 | */ 106 | abstract public function getHelp(); 107 | 108 | 109 | /** 110 | * Get market name 111 | * 112 | * @method getMarketName 113 | * 114 | * @return string 115 | */ 116 | abstract public function getMarketName(); 117 | } -------------------------------------------------------------------------------- /includes/MarketCheck/Settings.php: -------------------------------------------------------------------------------- 1 | 'marketcheck', 9 | 'access_level' => 'manage_options' 10 | ); 11 | 12 | function __construct( $fields ) 13 | { 14 | $this->fields = $fields; 15 | add_action( 'admin_menu', array( $this, 'add_admin_menu' ) ); 16 | add_action( 'admin_init', array( $this, 'register_settings' ) ); 17 | } 18 | 19 | public function getSettings() 20 | { 21 | if( !isset( $this->options ) ){ 22 | $this->options = get_option( $this->opts['namespace'] ); 23 | } 24 | 25 | return $this->options; 26 | } 27 | 28 | 29 | public function add_admin_menu() 30 | { 31 | add_options_page( 32 | 'MarketCheck', 33 | 'MarketCheck', 34 | $this->opts['access_level'], 35 | $this->opts['namespace'], 36 | array( $this, 'form' ) 37 | ); 38 | } 39 | 40 | 41 | public function register_settings() 42 | { 43 | register_setting( $this->opts['namespace'], $this->opts['namespace'] ); 44 | 45 | do_action( 'marketcheck/settings-fields', 46 | $this->opts['namespace'], $this->fields, $this->getSettings() ); 47 | 48 | $this->fields->addSection( 'General Settings', 'general_settings', $this->opts['namespace'] ); 49 | 50 | $this->fields->addCheckbox( array( 51 | "id" => 'disable_username', 52 | "title" => __( 'Disable Username input', 'marketcheck' ), 53 | "section_id" => 'general_settings', 54 | "namespace" => $this->opts['namespace'], 55 | "settings" => $this->getSettings(), 56 | "desc" => __( 'Disable the username field and use only the purchase code', 'marketcheck' ) 57 | ) ); 58 | 59 | 60 | $this->fields->addCheckbox( array( 61 | "id" => 'enable_credits', 62 | "title" => __( 'Display "Powered By"', 'marketcheck' ), 63 | "section_id" => 'general_settings', 64 | "namespace" => $this->opts['namespace'], 65 | "settings" => $this->getSettings(), 66 | "desc" => __( 'Display small credit line to help others find the plugin', 'marketcheck' ) 67 | ) ); 68 | } 69 | 70 | /** 71 | * Main Settings panel 72 | * 73 | * @since 1.0 74 | */ 75 | function form() { 76 | ?> 77 |
78 |
79 |

80 | 81 |
82 | opts['namespace'] ); 84 | do_settings_sections( $this->opts['namespace'] ); 85 | submit_button(); 86 | ?> 87 |
88 |
89 | addField( 'input', $args ); 12 | } 13 | 14 | 15 | public function addCheckbox( $args ) 16 | { 17 | $this->addField( 'checkbox', $args ); 18 | } 19 | 20 | public function addTextarea( $args ) 21 | { 22 | $this->addField( 'textarea', $args ); 23 | } 24 | 25 | 26 | public function addSection( $title, $id, $namespace ) 27 | { 28 | add_settings_section( $id, $title, '__return_false', $namespace ); 29 | } 30 | 31 | 32 | /** 33 | * Normalize field values 34 | * 35 | * @method parseArgs 36 | * 37 | * @param array $args 38 | * 39 | * @return array normalized array 40 | */ 41 | protected function parseArgs( $args ) 42 | { 43 | 44 | $id = $args['id']; 45 | 46 | $args['type'] = !empty( $args['type'] ) ? $args['type'] : 'input'; 47 | 48 | $args['value'] = !empty( $args['settings'][$id] ) ? $args['settings'][$id] : false; 49 | 50 | if( !empty( $args['default'] ) && is_null( $args['value'] ) ){ 51 | $args['value'] = $args['default']; 52 | } 53 | 54 | return $args; 55 | } 56 | 57 | 58 | /** 59 | * Display the description markup only when there is a description to show 60 | * 61 | * @method getDescription 62 | * 63 | * @param array $args 64 | * 65 | * @return string 66 | */ 67 | protected function getDescription( $args ) 68 | { 69 | if( !empty( $args['desc'] ) ){ 70 | return sprintf( '

%s

', $args['desc'] ); 71 | } 72 | } 73 | 74 | 75 | public function input( $args ) 76 | { 77 | $args = $this->parseArgs( $args ); 78 | 79 | $field = sprintf( '', 80 | $args['id'], 81 | $args['namespace'], 82 | $args['type'], 83 | esc_attr( $args['value'] ) 84 | ); 85 | 86 | $field .= $this->getDescription( $args ); 87 | 88 | echo $field; 89 | } 90 | 91 | 92 | public function textarea( $args ) 93 | { 94 | $args = $this->parseArgs( $args ); 95 | $field = sprintf( '', 96 | $args['id'], 97 | $args['namespace'], 98 | $args['value'] 99 | ); 100 | 101 | $field .= $this->getDescription( $args ); 102 | 103 | echo $field; 104 | } 105 | 106 | 107 | public function checkbox( $args ) 108 | { 109 | $args = $this->parseArgs( $args ); 110 | $field = sprintf( '', 111 | $args['id'], 112 | $args['namespace'], 113 | checked( $args['value'], 1, false ), 114 | $args['desc'] 115 | ); 116 | 117 | echo $field; 118 | } 119 | 120 | 121 | protected function addField( $fieldType, $args ){ 122 | // sample array: 123 | // array( 124 | // "id" => 'marketplace_username', 125 | // "title" => 'Envato Market Username', 126 | // "section_id" => '', 127 | // "namespace" => $namespace, 128 | // "settings" => $settings, 129 | // "desc" => __('Case sensitive', 'marketcheck'), 130 | // ); 131 | // 132 | add_settings_field( 133 | $args['id'], 134 | $args['title'], 135 | array( $this, $fieldType ), 136 | $args['namespace'], 137 | $args['section_id'], 138 | array( 139 | 'id' => $args['id'], 140 | 'namespace' => $args['namespace'], 141 | 'desc' => !empty( $args['desc'] ) ? $args['desc'] : null, 142 | 'settings' => $args['settings'], 143 | 'default' => isset( $args['default'] ) ? $args['default'] : null 144 | ) 145 | ); 146 | } 147 | } -------------------------------------------------------------------------------- /includes/MarketCheck/Settings/MarketSettings.php: -------------------------------------------------------------------------------- 1 | dbName = $dbName; 8 | } 9 | 10 | 11 | public function install() 12 | { 13 | global $wpdb; 14 | $charset_collate = $wpdb->get_charset_collate(); 15 | $table_name = $wpdb->prefix . $this->dbName; 16 | require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 17 | 18 | $sql = "CREATE TABLE {$table_name} ( 19 | id int(4) NOT NULL AUTO_INCREMENT, 20 | order_id varchar(250) NOT NULL, 21 | item_id varchar(250) NOT NULL, 22 | user_id int(4) NOT NULL, 23 | product_name varchar(250) NOT NULL, 24 | market_name varchar(250) NOT NULL, 25 | purchased_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, 26 | created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL, 27 | UNIQUE KEY id (id) 28 | ) {$charset_collate};"; 29 | 30 | dbDelta( $sql ); 31 | } 32 | } -------------------------------------------------------------------------------- /includes/MarketCheck/SignUp.php: -------------------------------------------------------------------------------- 1 | userManagement = $userManagement; 14 | 15 | add_action( 'login_form_register', array( $this, 'checkPurchaseForm' ) ); 16 | add_action( 'register_form', array( $this, 'registerForm' ) ); 17 | add_filter( 'registration_errors', array( $this, 'errors' ), 10, 3 ); 18 | add_action( 'user_register', array( $this, 'register' ) ); 19 | add_filter( 'shake_error_codes', array( $this, 'shaker' ) ); 20 | } 21 | 22 | 23 | function shaker( $shake_error_codes ) { 24 | $extras = array( 25 | 'invalid-market', 26 | 'empty_purchase', 27 | 'invalid_purchase_key', 28 | 'purchase_key_already_used' 29 | ); 30 | 31 | $shake_error_codes = array_merge( $extras, $shake_error_codes ); 32 | return $shake_error_codes; 33 | } 34 | 35 | 36 | public function addMarket( Markets\QueryMarket $market ) 37 | { 38 | $name = $market->getMarketName(); 39 | $this->markets[ $name ] = $market; 40 | } 41 | 42 | 43 | protected function getCurrentMarket() 44 | { 45 | $selectedMarket = $this->getSelectedMarket(); 46 | if( !$this->currentMarket && $selectedMarket ){ 47 | $this->currentMarket = $this->markets[ $selectedMarket ]; 48 | } 49 | 50 | return $this->currentMarket; 51 | } 52 | 53 | 54 | public function checkPurchaseForm() 55 | { 56 | $errors = new \WP_Error; 57 | $title = __( 'Check Purchase Key', 'marketcheck' ); 58 | 59 | $purchaseKey = $this->getPurchaseKey(); 60 | $selectedMarket = $this->getSelectedMarket(); 61 | $isSubmited = $this->getPostVar( 'marketcheck-submitted' ); 62 | 63 | if( $isSubmited ){ 64 | if( !$selectedMarket ){ 65 | $errors->add( 'invalid-market', __( 'Error: Invalid Market Selected.', 'marketcheck' ) ); 66 | } 67 | 68 | if( !$purchaseKey ){ 69 | $errors->add( 'empty_purchase', __( 'Error: Empty Purchase Code.', 'marketcheck' ) ); 70 | } 71 | } 72 | 73 | if( $isSubmited && $selectedMarket && $purchaseKey ) { 74 | $this->getCurrentMarket()->setPurchaseKey( $purchaseKey ); 75 | $isValidPurchase = $this->getCurrentMarket()->isValidPurchase(); 76 | if( is_wp_error( $isValidPurchase ) ){ 77 | $errors = $isValidPurchase; 78 | } else { 79 | return; 80 | } 81 | } 82 | 83 | login_header( $title, '

' . $title, $errors ); 84 | $this->showPreRegisterForm(); 85 | login_footer('purchase-key'); 86 | die(); 87 | } 88 | 89 | 90 | public function registerForm() 91 | { 92 | $this->showMarketSelector(); 93 | ?> 94 | 95 | 96 | 97 | getPurchaseKey() ){ 104 | $errors->add( 'invalid_purchase_key', __( 'ERROR: Invalid Purchase Key.', 'marketcheck' ) ); 105 | } 106 | 107 | if( $this->getPostVar( 'marketcheck-submitted' ) == 1 ){ 108 | $errors->remove('empty_username'); 109 | $errors->remove('empty_email'); 110 | $errors->add('fill-register-form', __( 'Please fill the register form', 'marketcheck' ) ); 111 | } 112 | 113 | return $errors; 114 | } 115 | 116 | 117 | public function register( $userID ) 118 | { 119 | $this->getCurrentMarket()->setPurchaseKey( $this->getPurchaseKey() ); 120 | $this->userManagement->addUser( $userID, $this->getCurrentMarket()->getProduct() ); 121 | } 122 | 123 | 124 | protected function showPreRegisterForm() 125 | { 126 | ?> 127 | 128 | 134 | 135 |

136 |

137 | 146 | 147 |

148 | 149 | showMarketSelector() ?> 150 | 151 |
152 | 153 |

154 | 161 |

162 |
163 | 164 | getSelectedMarket(); 171 | $selectMarketplaceText = __( 'Select Marketplace', 'marketcheck' ); 172 | $help = array(); 173 | 174 | if( $this->getPostVar( 'marketcheck-submitted' ) && $selectedMarket ){ 175 | ?> 176 | 177 | markets ) < 2 ){ 179 | $market = key( $this->markets ); 180 | ?> 181 | 182 | markets[ $market ]->getHelp(); 184 | } else { 185 | ?> 186 |

187 |
188 | 201 | "; 205 | } 206 | 207 | 208 | protected function getSelectedMarket() 209 | { 210 | return $this->getPostVar( 'market-selector' ); 211 | } 212 | 213 | 214 | protected function getPurchaseKey() 215 | { 216 | return $this->getPostVar( 'purchase-key' ); 217 | } 218 | 219 | 220 | protected function getPostVar( $varName ) 221 | { 222 | return isset( $_POST[ $varName ] ) ? trim( esc_attr( $_POST[ $varName ] ) ) : null; 223 | } 224 | } -------------------------------------------------------------------------------- /includes/MarketCheck/UserManagement.php: -------------------------------------------------------------------------------- 1 | db = $db; 8 | add_action( 'delete_user', array( $this, 'deleteUser' ) ); 9 | } 10 | 11 | public function addUser( $userID, $product ) 12 | { 13 | $wpdb = $this->db->wpdb(); 14 | 15 | $wpdb->insert( 16 | $this->db->getDbName(), 17 | array( 18 | 'order_id' => $product['order_id'], 19 | 'item_id' => $product['id'], 20 | 'user_id' => $userID, 21 | 'purchased_at' => date('Y-m-d H:i:s', strtotime( $product['purchased_at'] ) ), 22 | 'product_name' => $product['name'], 23 | 'market_name' => $product['market_name'] 24 | ), 25 | array( 26 | '%s', 27 | '%s', 28 | '%d', 29 | '%s', 30 | '%s' 31 | ) 32 | ); 33 | 34 | 35 | if( function_exists( 'bbp_set_user_role' ) ){ 36 | bbp_set_user_role( $userID, 'participant' ); 37 | } 38 | 39 | $items = array( $product['id'] ); 40 | 41 | // add a hook to allow adding extra user meta (or whatever) 42 | do_action( 'marketcheck/registered_user', $userID, $product, $wpdb->insert_id ); 43 | 44 | update_user_meta( $userID, 'marketcheck_purchased_items', $items ); 45 | } 46 | 47 | 48 | public function deleteUser( $userID ) 49 | { 50 | $this->db->wpdb()->delete( $this->db->getDbName(), array( 'user_id' => $userID ), array( '%d' ) ); 51 | } 52 | } -------------------------------------------------------------------------------- /lang/dummy.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iamntz/MarketCheck/c5f6b91765773cdb7b16bdfc6065940701f0ff6d/lang/dummy.mo -------------------------------------------------------------------------------- /register-custom-markets.php: -------------------------------------------------------------------------------- 1 | addMarket( new Envato\QueryMarket( $settings, $db ) ); 8 | 9 | new Mojo\Settings(); 10 | $registerForm->addMarket( new Mojo\QueryMarket( $settings, $db ) ); 11 | }, 10, 4 ); 12 | -------------------------------------------------------------------------------- /vendor/autoload.php: -------------------------------------------------------------------------------- 1 | 7 | * Jordi Boggiano 8 | * 9 | * For the full copyright and license information, please view the LICENSE 10 | * file that was distributed with this source code. 11 | */ 12 | 13 | namespace Composer\Autoload; 14 | 15 | /** 16 | * ClassLoader implements a PSR-0 class loader 17 | * 18 | * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md 19 | * 20 | * $loader = new \Composer\Autoload\ClassLoader(); 21 | * 22 | * // register classes with namespaces 23 | * $loader->add('Symfony\Component', __DIR__.'/component'); 24 | * $loader->add('Symfony', __DIR__.'/framework'); 25 | * 26 | * // activate the autoloader 27 | * $loader->register(); 28 | * 29 | * // to enable searching the include path (eg. for PEAR packages) 30 | * $loader->setUseIncludePath(true); 31 | * 32 | * In this example, if you try to use a class in the Symfony\Component 33 | * namespace or one of its children (Symfony\Component\Console for instance), 34 | * the autoloader will first look for the class under the component/ 35 | * directory, and it will then fallback to the framework/ directory if not 36 | * found before giving up. 37 | * 38 | * This class is loosely based on the Symfony UniversalClassLoader. 39 | * 40 | * @author Fabien Potencier 41 | * @author Jordi Boggiano 42 | */ 43 | class ClassLoader 44 | { 45 | // PSR-4 46 | private $prefixLengthsPsr4 = array(); 47 | private $prefixDirsPsr4 = array(); 48 | private $fallbackDirsPsr4 = array(); 49 | 50 | // PSR-0 51 | private $prefixesPsr0 = array(); 52 | private $fallbackDirsPsr0 = array(); 53 | 54 | private $useIncludePath = false; 55 | private $classMap = array(); 56 | 57 | private $classMapAuthoritative = false; 58 | 59 | public function getPrefixes() 60 | { 61 | if (!empty($this->prefixesPsr0)) { 62 | return call_user_func_array('array_merge', $this->prefixesPsr0); 63 | } 64 | 65 | return array(); 66 | } 67 | 68 | public function getPrefixesPsr4() 69 | { 70 | return $this->prefixDirsPsr4; 71 | } 72 | 73 | public function getFallbackDirs() 74 | { 75 | return $this->fallbackDirsPsr0; 76 | } 77 | 78 | public function getFallbackDirsPsr4() 79 | { 80 | return $this->fallbackDirsPsr4; 81 | } 82 | 83 | public function getClassMap() 84 | { 85 | return $this->classMap; 86 | } 87 | 88 | /** 89 | * @param array $classMap Class to filename map 90 | */ 91 | public function addClassMap(array $classMap) 92 | { 93 | if ($this->classMap) { 94 | $this->classMap = array_merge($this->classMap, $classMap); 95 | } else { 96 | $this->classMap = $classMap; 97 | } 98 | } 99 | 100 | /** 101 | * Registers a set of PSR-0 directories for a given prefix, either 102 | * appending or prepending to the ones previously set for this prefix. 103 | * 104 | * @param string $prefix The prefix 105 | * @param array|string $paths The PSR-0 root directories 106 | * @param bool $prepend Whether to prepend the directories 107 | */ 108 | public function add($prefix, $paths, $prepend = false) 109 | { 110 | if (!$prefix) { 111 | if ($prepend) { 112 | $this->fallbackDirsPsr0 = array_merge( 113 | (array) $paths, 114 | $this->fallbackDirsPsr0 115 | ); 116 | } else { 117 | $this->fallbackDirsPsr0 = array_merge( 118 | $this->fallbackDirsPsr0, 119 | (array) $paths 120 | ); 121 | } 122 | 123 | return; 124 | } 125 | 126 | $first = $prefix[0]; 127 | if (!isset($this->prefixesPsr0[$first][$prefix])) { 128 | $this->prefixesPsr0[$first][$prefix] = (array) $paths; 129 | 130 | return; 131 | } 132 | if ($prepend) { 133 | $this->prefixesPsr0[$first][$prefix] = array_merge( 134 | (array) $paths, 135 | $this->prefixesPsr0[$first][$prefix] 136 | ); 137 | } else { 138 | $this->prefixesPsr0[$first][$prefix] = array_merge( 139 | $this->prefixesPsr0[$first][$prefix], 140 | (array) $paths 141 | ); 142 | } 143 | } 144 | 145 | /** 146 | * Registers a set of PSR-4 directories for a given namespace, either 147 | * appending or prepending to the ones previously set for this namespace. 148 | * 149 | * @param string $prefix The prefix/namespace, with trailing '\\' 150 | * @param array|string $paths The PSR-0 base directories 151 | * @param bool $prepend Whether to prepend the directories 152 | * 153 | * @throws \InvalidArgumentException 154 | */ 155 | public function addPsr4($prefix, $paths, $prepend = false) 156 | { 157 | if (!$prefix) { 158 | // Register directories for the root namespace. 159 | if ($prepend) { 160 | $this->fallbackDirsPsr4 = array_merge( 161 | (array) $paths, 162 | $this->fallbackDirsPsr4 163 | ); 164 | } else { 165 | $this->fallbackDirsPsr4 = array_merge( 166 | $this->fallbackDirsPsr4, 167 | (array) $paths 168 | ); 169 | } 170 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) { 171 | // Register directories for a new namespace. 172 | $length = strlen($prefix); 173 | if ('\\' !== $prefix[$length - 1]) { 174 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 175 | } 176 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 177 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 178 | } elseif ($prepend) { 179 | // Prepend directories for an already registered namespace. 180 | $this->prefixDirsPsr4[$prefix] = array_merge( 181 | (array) $paths, 182 | $this->prefixDirsPsr4[$prefix] 183 | ); 184 | } else { 185 | // Append directories for an already registered namespace. 186 | $this->prefixDirsPsr4[$prefix] = array_merge( 187 | $this->prefixDirsPsr4[$prefix], 188 | (array) $paths 189 | ); 190 | } 191 | } 192 | 193 | /** 194 | * Registers a set of PSR-0 directories for a given prefix, 195 | * replacing any others previously set for this prefix. 196 | * 197 | * @param string $prefix The prefix 198 | * @param array|string $paths The PSR-0 base directories 199 | */ 200 | public function set($prefix, $paths) 201 | { 202 | if (!$prefix) { 203 | $this->fallbackDirsPsr0 = (array) $paths; 204 | } else { 205 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; 206 | } 207 | } 208 | 209 | /** 210 | * Registers a set of PSR-4 directories for a given namespace, 211 | * replacing any others previously set for this namespace. 212 | * 213 | * @param string $prefix The prefix/namespace, with trailing '\\' 214 | * @param array|string $paths The PSR-4 base directories 215 | * 216 | * @throws \InvalidArgumentException 217 | */ 218 | public function setPsr4($prefix, $paths) 219 | { 220 | if (!$prefix) { 221 | $this->fallbackDirsPsr4 = (array) $paths; 222 | } else { 223 | $length = strlen($prefix); 224 | if ('\\' !== $prefix[$length - 1]) { 225 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); 226 | } 227 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; 228 | $this->prefixDirsPsr4[$prefix] = (array) $paths; 229 | } 230 | } 231 | 232 | /** 233 | * Turns on searching the include path for class files. 234 | * 235 | * @param bool $useIncludePath 236 | */ 237 | public function setUseIncludePath($useIncludePath) 238 | { 239 | $this->useIncludePath = $useIncludePath; 240 | } 241 | 242 | /** 243 | * Can be used to check if the autoloader uses the include path to check 244 | * for classes. 245 | * 246 | * @return bool 247 | */ 248 | public function getUseIncludePath() 249 | { 250 | return $this->useIncludePath; 251 | } 252 | 253 | /** 254 | * Turns off searching the prefix and fallback directories for classes 255 | * that have not been registered with the class map. 256 | * 257 | * @param bool $classMapAuthoritative 258 | */ 259 | public function setClassMapAuthoritative($classMapAuthoritative) 260 | { 261 | $this->classMapAuthoritative = $classMapAuthoritative; 262 | } 263 | 264 | /** 265 | * Should class lookup fail if not found in the current class map? 266 | * 267 | * @return bool 268 | */ 269 | public function isClassMapAuthoritative() 270 | { 271 | return $this->classMapAuthoritative; 272 | } 273 | 274 | /** 275 | * Registers this instance as an autoloader. 276 | * 277 | * @param bool $prepend Whether to prepend the autoloader or not 278 | */ 279 | public function register($prepend = false) 280 | { 281 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 282 | } 283 | 284 | /** 285 | * Unregisters this instance as an autoloader. 286 | */ 287 | public function unregister() 288 | { 289 | spl_autoload_unregister(array($this, 'loadClass')); 290 | } 291 | 292 | /** 293 | * Loads the given class or interface. 294 | * 295 | * @param string $class The name of the class 296 | * @return bool|null True if loaded, null otherwise 297 | */ 298 | public function loadClass($class) 299 | { 300 | if ($file = $this->findFile($class)) { 301 | includeFile($file); 302 | 303 | return true; 304 | } 305 | } 306 | 307 | /** 308 | * Finds the path to the file where the class is defined. 309 | * 310 | * @param string $class The name of the class 311 | * 312 | * @return string|false The path if found, false otherwise 313 | */ 314 | public function findFile($class) 315 | { 316 | // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 317 | if ('\\' == $class[0]) { 318 | $class = substr($class, 1); 319 | } 320 | 321 | // class map lookup 322 | if (isset($this->classMap[$class])) { 323 | return $this->classMap[$class]; 324 | } 325 | if ($this->classMapAuthoritative) { 326 | return false; 327 | } 328 | 329 | $file = $this->findFileWithExtension($class, '.php'); 330 | 331 | // Search for Hack files if we are running on HHVM 332 | if ($file === null && defined('HHVM_VERSION')) { 333 | $file = $this->findFileWithExtension($class, '.hh'); 334 | } 335 | 336 | if ($file === null) { 337 | // Remember that this class does not exist. 338 | return $this->classMap[$class] = false; 339 | } 340 | 341 | return $file; 342 | } 343 | 344 | private function findFileWithExtension($class, $ext) 345 | { 346 | // PSR-4 lookup 347 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; 348 | 349 | $first = $class[0]; 350 | if (isset($this->prefixLengthsPsr4[$first])) { 351 | foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { 352 | if (0 === strpos($class, $prefix)) { 353 | foreach ($this->prefixDirsPsr4[$prefix] as $dir) { 354 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { 355 | return $file; 356 | } 357 | } 358 | } 359 | } 360 | } 361 | 362 | // PSR-4 fallback dirs 363 | foreach ($this->fallbackDirsPsr4 as $dir) { 364 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { 365 | return $file; 366 | } 367 | } 368 | 369 | // PSR-0 lookup 370 | if (false !== $pos = strrpos($class, '\\')) { 371 | // namespaced class name 372 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) 373 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); 374 | } else { 375 | // PEAR-like class name 376 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; 377 | } 378 | 379 | if (isset($this->prefixesPsr0[$first])) { 380 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { 381 | if (0 === strpos($class, $prefix)) { 382 | foreach ($dirs as $dir) { 383 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 384 | return $file; 385 | } 386 | } 387 | } 388 | } 389 | } 390 | 391 | // PSR-0 fallback dirs 392 | foreach ($this->fallbackDirsPsr0 as $dir) { 393 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { 394 | return $file; 395 | } 396 | } 397 | 398 | // PSR-0 include paths. 399 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { 400 | return $file; 401 | } 402 | } 403 | } 404 | 405 | /** 406 | * Scope isolated include. 407 | * 408 | * Prevents access to $this/self from included files. 409 | */ 410 | function includeFile($file) 411 | { 412 | include $file; 413 | } 414 | -------------------------------------------------------------------------------- /vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | array($baseDir . '/includes'), 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/composer/autoload_psr4.php: -------------------------------------------------------------------------------- 1 | $path) { 28 | $loader->set($namespace, $path); 29 | } 30 | 31 | $map = require __DIR__ . '/autoload_psr4.php'; 32 | foreach ($map as $namespace => $path) { 33 | $loader->setPsr4($namespace, $path); 34 | } 35 | 36 | $classMap = require __DIR__ . '/autoload_classmap.php'; 37 | if ($classMap) { 38 | $loader->addClassMap($classMap); 39 | } 40 | 41 | $loader->register(true); 42 | 43 | return $loader; 44 | } 45 | } 46 | 47 | function composerRequirefa37c385d03cd13f1a2aac56c07ae62b($file) 48 | { 49 | require $file; 50 | } 51 | --------------------------------------------------------------------------------