diff --git a/.github/workflows/phpcs.yml b/.github/workflows/phpcs.yml index 98fd7988..d94b57da 100644 --- a/.github/workflows/phpcs.yml +++ b/.github/workflows/phpcs.yml @@ -11,7 +11,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: "7.3" + php-version: "7.4" coverage: none tools: composer, cs2pr diff --git a/composer.json b/composer.json index e9347ec8..3b7bda83 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ ], "require": { "php": ">=5.5", - "league/csv": "^7.2", + "league/csv": "9.8", "appsero/client": "v2.0.4" }, "require-dev": { diff --git a/composer.lock b/composer.lock index c066b826..e46cb9c9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a2fe228cac617207769d110eeea55340", + "content-hash": "942fcc0350a4e5312066bccd2765e5a2", "packages": [ { "name": "appsero/client", @@ -62,33 +62,46 @@ }, { "name": "league/csv", - "version": "7.2.0", + "version": "9.8.0", "source": { "type": "git", "url": "https://github.com/thephpleague/csv.git", - "reference": "69bafa6ff924fbf9effe4275d6eb16be81a853ef" + "reference": "9d2e0265c5d90f5dd601bc65ff717e05cec19b47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/csv/zipball/69bafa6ff924fbf9effe4275d6eb16be81a853ef", - "reference": "69bafa6ff924fbf9effe4275d6eb16be81a853ef", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/9d2e0265c5d90f5dd601bc65ff717e05cec19b47", + "reference": "9d2e0265c5d90f5dd601bc65ff717e05cec19b47", "shasum": "" }, "require": { + "ext-json": "*", "ext-mbstring": "*", - "php": ">=5.4.0" + "php": "^7.4 || ^8.0" }, "require-dev": { - "fabpot/php-cs-fixer": "^1.9", - "phpunit/phpunit": "^4.0" + "ext-curl": "*", + "ext-dom": "*", + "friendsofphp/php-cs-fixer": "^v3.4.0", + "phpstan/phpstan": "^1.3.0", + "phpstan/phpstan-phpunit": "^1.0.0", + "phpstan/phpstan-strict-rules": "^1.1.0", + "phpunit/phpunit": "^9.5.11" + }, + "suggest": { + "ext-dom": "Required to use the XMLConverter and or the HTMLConverter classes", + "ext-iconv": "Needed to ease transcoding CSV using iconv stream filters" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "7.2-dev" + "dev-master": "9.x-dev" } }, "autoload": { + "files": [ + "src/functions_include.php" + ], "psr-4": { "League\\Csv\\": "src" } @@ -105,22 +118,31 @@ "role": "Developer" } ], - "description": "Csv data manipulation made easy in PHP", - "homepage": "http://csv.thephpleague.com", + "description": "CSV data manipulation made easy in PHP", + "homepage": "https://csv.thephpleague.com", "keywords": [ + "convert", "csv", "export", "filter", "import", "read", + "transform", "write" ], "support": { - "forum": "https://groups.google.com/forum/#!forum/thephpleague", + "docs": "https://csv.thephpleague.com", "issues": "https://github.com/thephpleague/csv/issues", - "source": "https://github.com/thephpleague/csv/tree/master" + "rss": "https://github.com/thephpleague/csv/releases.atom", + "source": "https://github.com/thephpleague/csv" }, - "time": "2015-11-02T07:36:25+00:00" + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2022-01-04T00:13:07+00:00" } ], "packages-dev": [ @@ -339,17 +361,18 @@ "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", - "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082" + "reference": "ab217cfc57bebbf3efa44fa059baafd0d9e4064c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/01c1ff2704a58e46f0cb1ca9d06aee07b3589082", - "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/ab217cfc57bebbf3efa44fa059baafd0d9e4064c", + "reference": "ab217cfc57bebbf3efa44fa059baafd0d9e4064c", "shasum": "" }, "require": { "phpcompatibility/php-compatibility": "^9.0", - "phpcompatibility/phpcompatibility-paragonie": "^1.0" + "phpcompatibility/phpcompatibility-paragonie": "^1.0", + "squizlabs/php_codesniffer": "^3.3" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0" @@ -400,35 +423,39 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" } ], - "time": "2024-04-24T21:37:59+00:00" + "time": "2025-06-13T07:13:41+00:00" }, { "name": "phpcsstandards/phpcsextra", - "version": "1.2.1", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", - "reference": "11d387c6642b6e4acaf0bd9bf5203b8cca1ec489" + "reference": "fa4b8d051e278072928e32d817456a7fdb57b6ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/11d387c6642b6e4acaf0bd9bf5203b8cca1ec489", - "reference": "11d387c6642b6e4acaf0bd9bf5203b8cca1ec489", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/fa4b8d051e278072928e32d817456a7fdb57b6ca", + "reference": "fa4b8d051e278072928e32d817456a7fdb57b6ca", "shasum": "" }, "require": { "php": ">=5.4", - "phpcsstandards/phpcsutils": "^1.0.9", - "squizlabs/php_codesniffer": "^3.8.0" + "phpcsstandards/phpcsutils": "^1.1.0", + "squizlabs/php_codesniffer": "^3.13.0 || ^4.0" }, "require-dev": { "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3.2", + "php-parallel-lint/php-parallel-lint": "^1.4.0", "phpcsstandards/phpcsdevcs": "^1.1.6", "phpcsstandards/phpcsdevtools": "^1.2.1", - "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "type": "phpcodesniffer-standard", "extra": { @@ -478,35 +505,39 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2023-12-08T16:49:07+00:00" + "time": "2025-06-14T07:40:39+00:00" }, { "name": "phpcsstandards/phpcsutils", - "version": "1.0.12", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", - "reference": "87b233b00daf83fb70f40c9a28692be017ea7c6c" + "reference": "65355670ac17c34cd235cf9d3ceae1b9252c4dad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/87b233b00daf83fb70f40c9a28692be017ea7c6c", - "reference": "87b233b00daf83fb70f40c9a28692be017ea7c6c", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/65355670ac17c34cd235cf9d3ceae1b9252c4dad", + "reference": "65355670ac17c34cd235cf9d3ceae1b9252c4dad", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.10.0 || 4.0.x-dev@dev" + "squizlabs/php_codesniffer": "^3.13.0 || ^4.0" }, "require-dev": { "ext-filter": "*", "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3.2", + "php-parallel-lint/php-parallel-lint": "^1.4.0", "phpcsstandards/phpcsdevcs": "^1.1.6", - "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0" + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0" }, "type": "phpcodesniffer-standard", "extra": { @@ -543,6 +574,7 @@ "phpcodesniffer-standard", "phpcs", "phpcs3", + "phpcs4", "standards", "static analysis", "tokens", @@ -566,22 +598,26 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2024-05-20T13:34:27+00:00" + "time": "2025-06-12T04:32:33+00:00" }, { "name": "squizlabs/php_codesniffer", - "version": "3.10.2", + "version": "3.13.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017" + "reference": "5b5e3821314f947dd040c70f7992a64eac89025c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/86e5f5dd9a840c46810ebe5ff1885581c42a3017", - "reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/5b5e3821314f947dd040c70f7992a64eac89025c", + "reference": "5b5e3821314f947dd040c70f7992a64eac89025c", "shasum": "" }, "require": { @@ -646,26 +682,31 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2024-07-21T23:26:44+00:00" + "time": "2025-06-17T22:17:01+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.30.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", - "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -676,8 +717,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -712,7 +753,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -728,30 +769,30 @@ "type": "tidelift" } ], - "time": "2024-06-19T12:30:46+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.30.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433" + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/77fa7995ac1b21ab60769b7323d600a991a90433", - "reference": "77fa7995ac1b21ab60769b7323d600a991a90433", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -792,7 +833,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" }, "funding": [ { @@ -808,20 +849,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { "name": "symfony/var-dumper", - "version": "v5.4.42", + "version": "v5.4.48", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "0c17c56d8ea052fc33942251c75d0e28936e043d" + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/0c17c56d8ea052fc33942251c75d0e28936e043d", - "reference": "0c17c56d8ea052fc33942251c75d0e28936e043d", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/42f18f170aa86d612c3559cfb3bd11a375df32c8", + "reference": "42f18f170aa86d612c3559cfb3bd11a375df32c8", "shasum": "" }, "require": { @@ -881,7 +922,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.4.42" + "source": "https://github.com/symfony/var-dumper/tree/v5.4.48" }, "funding": [ { @@ -897,7 +938,7 @@ "type": "tidelift" } ], - "time": "2024-07-26T12:23:09+00:00" + "time": "2024-11-08T15:21:10+00:00" }, { "name": "tareq1988/wp-php-cs-fixer", @@ -1007,15 +1048,15 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { - "wp-coding-standards/wpcs": 20, + "phpcompatibility/phpcompatibility-wp": 20, "tareq1988/wp-php-cs-fixer": 20, - "phpcompatibility/phpcompatibility-wp": 20 + "wp-coding-standards/wpcs": 20 }, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=5.5" }, - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/includes/Admin/Notice.php b/includes/Admin/Notice.php index 94c192a5..11dcecc7 100644 --- a/includes/Admin/Notice.php +++ b/includes/Admin/Notice.php @@ -71,7 +71,7 @@ public function connect_notice() { update_option( 'wemail_site_connection_notice', 1 ); } } - if ( ! get_user_meta( get_current_user_id(), 'wemail_api_key', true ) && (int) get_option( 'wemail_site_connection_notice' ) !== 1 && ! ( isset( $_GET['page'] ) && $_GET['page'] === 'wemail' ) ) { + if ( ! get_option( 'wemail_api_key' ) && (int) get_option( 'wemail_site_connection_notice' ) !== 1 && ! ( isset( $_GET['page'] ) && $_GET['page'] === 'wemail' ) ) { add_action( 'admin_notices', array( $this, 'connect_notice_html' ) ); } } diff --git a/includes/Admin/Scripts.php b/includes/Admin/Scripts.php index 7886b6c8..fae49db2 100644 --- a/includes/Admin/Scripts.php +++ b/includes/Admin/Scripts.php @@ -139,7 +139,8 @@ public function enqueue_scripts() { 'user' => array( 'hash' => $user->hash, 'role' => $user->role, - 'permissions' => $user->permissions, + 'allowed' => $user->allowed, + // 'permissions' => $user->permissions, ), 'currentUser' => $current_user ? array( 'name' => $current_user->display_name, diff --git a/includes/Core/Api/Api.php b/includes/Core/Api/Api.php index b8d87970..f9ce5bc1 100644 --- a/includes/Core/Api/Api.php +++ b/includes/Core/Api/Api.php @@ -169,6 +169,17 @@ public function has_api_key() { return (bool) $this->api_key; } + /** + * Added url + * + * @param [string] $url + * @return void + */ + public function url( $url ) { + $this->url = $url; + return $this; + } + /** * Magic method to set resource and endpoints * @@ -367,7 +378,25 @@ public function send_json( $json = true ) { * @return mixed */ public function put( $data, $args = array() ) { - $data['_method'] = 'put'; + $args = $this->args( $args ); + $args['method'] = 'PUT'; + + return $this->post( $data, $args ); + } + + /** + * API - PATCH request caller + * + * @since 2.0.0 + * + * @param array $data PUT data + * @param array $args wp_remote_request argument overrides + * + * @return mixed + */ + public function patch( $data, $args = array() ) { + $args = $this->args( $args ); + $args['method'] = 'PATCH'; return $this->post( $data, $args ); } @@ -385,15 +414,9 @@ public function put( $data, $args = array() ) { public function delete( $data = array(), $args = array() ) { $args = $this->args( $args ); - $args['method'] = 'delete'; + $args['method'] = 'DELETE'; - $args['body'] = ! empty( $data ) ? $data : null; - - $url = $this->build_url(); - - $response = wp_remote_request( $url, $args ); - - return $this->response( $response ); + return $this->post( $data, $args ); } /** diff --git a/includes/Core/User/Integrations/WpUser.php b/includes/Core/User/Integrations/WpUser.php index acf31c2f..0e6b115c 100644 --- a/includes/Core/User/Integrations/WpUser.php +++ b/includes/Core/User/Integrations/WpUser.php @@ -47,7 +47,7 @@ public function wemail_user_profile_updated( $user_id, $old_user_data ) { return; } - $access_token = get_user_meta( $user_id, 'wemail_api_key', true ); + $access_token = get_option( 'wemail_api_key' ); if ( empty( $access_token ) ) { return; @@ -56,7 +56,6 @@ public function wemail_user_profile_updated( $user_id, $old_user_data ) { $data = array( 'name' => $user->data->display_name, 'email' => $user->data->user_email, - 'token' => $access_token, ); $response = wemail()->api->set_api_key( $access_token )->auth()->users()->profile()->update()->post( $data ); @@ -65,7 +64,7 @@ public function wemail_user_profile_updated( $user_id, $old_user_data ) { return; } - $this->update_user_permission( $access_token, $user_id ); + // $this->update_user_permission( $access_token, $user_id ); } /** @@ -174,9 +173,9 @@ protected function create_wemail_user( $user, $role ) { return; } - update_user_meta( $user->ID, 'wemail_api_key', $response['access_token'] ); + // update_user_meta( $user->ID, 'wemail_api_key', $response['access_token'] ); - $this->update_user_permission( $response['access_token'], $user->ID ); + // $this->update_user_permission( $response['access_token'], $user->ID ); } /** @@ -186,17 +185,17 @@ protected function create_wemail_user( $user, $role ) { * @param $user_id */ protected function update_user_permission( $access_token, $user_id ) { - $api_key = apply_filters( 'wemail_api_key', $access_token ); - $user_data = wemail()->api->set_api_key( $api_key )->auth()->users()->me()->query( array( 'include' => 'role,permissions' ) )->get(); + // $api_key = apply_filters( 'wemail_api_key', $access_token ); + // $user_data = wemail()->api->set_api_key( $api_key )->auth()->users()->me()->query( array( 'include' => 'role,permissions' ) )->get(); - if ( is_wp_error( $user_data ) ) { - return; - } + // if ( is_wp_error( $user_data ) ) { + // return; + // } - if ( ! empty( $user_data['data'] ) ) { - $user_data = $user_data['data']; + // if ( ! empty( $user_data['data'] ) ) { + // $user_data = $user_data['data']; - update_user_meta( $user_id, 'wemail_user_data', $user_data ); - } + // update_user_meta( $user_id, 'wemail_user_data', $user_data ); + // } } } diff --git a/includes/Core/User/User.php b/includes/Core/User/User.php index 0bd853bb..7b4a995a 100644 --- a/includes/Core/User/User.php +++ b/includes/Core/User/User.php @@ -45,13 +45,13 @@ class User { public $role = null; /** - * User permissions + * Is user allowed to access weMail * - * @since 1.0.0 + * @since 1.14.16 * - * @var array + * @var boolean */ - public $permissions = array(); + public $allowed = false; /** * API resource query for URL to build @@ -74,25 +74,9 @@ public function boot() { $api_key = apply_filters( 'wemail_api_key', $api_key, $user_id ); if ( $api_key ) { - $user_data = get_user_meta( $user_id, 'wemail_user_data', true ); - $this->check_user_role($user_id); - if ( ! $user_data ) { - $user_data = wemail()->api->wp()->users()->rolePermissions()->query( array( 'email' => $user_email ) )->get(); - - if ( is_wp_error( $user_data ) ) { - return; - } - - if ( ! empty( $user_data['data'] ) ) { - $user_data = $user_data['data']; - - update_user_meta( $user_id, 'wemail_user_data', $user_data ); - } - } - - $this->hash = $user_data['hash']; - $this->role = $user_data['role']; - $this->permissions = $user_data['permissions']; + $this->hash = $api_key ? true : false; + $this->role = wp_get_current_user()->roles; + $this->allowed = $this->check_user_role( $user_id ); } $this->user_id = $user_id; @@ -109,23 +93,31 @@ public function boot() { * @return bool */ public function can( $permission ) { - if ( $this->permissions && array_key_exists( $permission, $this->permissions ) ) { - return true; - } + // if ( $this->permissions && array_key_exists( $permission, $this->permissions ) ) { + // return true; + // } + + return $this->check_user_role( $this->user_id ); - return false; + // return false; } - public function check_user_role($user_id) - { - $accessible_roles = get_option( 'wemail_accessible_roles' ); - if (!empty(array_intersect(wp_get_current_user()->roles, $accessible_roles)) && empty($this->permissions)) { - delete_user_meta($user_id, 'wemail_user_data'); - } - if (empty(array_intersect(wp_get_current_user()->roles, $accessible_roles))) { - if (get_user_meta( $user_id, 'wemail_user_data', true )) { - delete_user_meta($user_id, 'wemail_user_data'); + public function check_user_role( $user_id ) { + $accessible_roles = get_option( 'wemail_accessible_roles', array() ); + $current_roles = wp_get_current_user()->roles; + + // Check if user has any accessible role + $has_accessible_role = ! empty( array_intersect( $current_roles, $accessible_roles ) ); + + if ( $has_accessible_role ) { + // User has accessible role - keep their data + return true; + } else { + // User doesn't have accessible role - delete their data + if ( get_user_meta( $user_id, 'wemail_user_data', true ) ) { + delete_user_meta( $user_id, 'wemail_user_data' ); } + return false; } } } diff --git a/includes/Core/Users/Menu.php b/includes/Core/Users/Menu.php index 2189f809..674fbc3b 100644 --- a/includes/Core/Users/Menu.php +++ b/includes/Core/Users/Menu.php @@ -39,7 +39,7 @@ public function __construct() { * @return array */ public function register_submenu( $menu_items, $capability ) { - if (wemail()->user->can('manage_settings') && in_array('administrator', wp_get_current_user()->roles, true) ) { + if ( wemail()->user->can( 'manage_settings' ) && in_array( 'administrator', wp_get_current_user()->roles, true ) ) { $menu_items[] = array( __( 'Teams', 'wemail' ), $capability, diff --git a/includes/Hooks.php b/includes/Hooks.php index 88e825ad..b2f73295 100644 --- a/includes/Hooks.php +++ b/includes/Hooks.php @@ -16,7 +16,7 @@ public function __construct() { new FormIntegrations(); new SyncSubscriberWp(); new SyncSubscriberErp(); -// new SyncWpUser(); + // new SyncWpUser(); new MailHooks(); Ecommerce::instance(); new SyncAffiliateWp(); diff --git a/includes/Rest/Csv.php b/includes/Rest/Csv.php index 304ddc1f..1e67c620 100644 --- a/includes/Rest/Csv.php +++ b/includes/Rest/Csv.php @@ -120,10 +120,10 @@ public function csv_file_info( $request ) { $reader = $this->reader( $file_id ); - $query = $reader->query(); + $count = iterator_count( $reader ); $data = array( - 'total' => iterator_count( $query ) - 1, + 'total' => $count - 1, // Subtract 1 for header row ); return new WP_REST_Response( $data, 200 ); @@ -155,14 +155,16 @@ public function subscribers( $request ) { $reader = $this->reader( $file_id ); - $meta_fields = $reader->fetchOne(); - $meta_fields = array_filter( $meta_fields ); - $meta_fields = array_unique( $meta_fields ); + // Set the header offset so records are returned as associative arrays + $reader->setHeaderOffset( 0 ); + + // Use Statement for offset/limit + $stmt = \League\Csv\Statement::create() + ->offset( $offset ) + ->limit( $limit ); - $subscribers = $reader - ->setOffset( $offset + 1 ) // +1 to ignore the header - ->setLimit( $limit ) - ->fetchAssoc( $meta_fields ); + $records = $stmt->process( $reader ); // Iterator of associative arrays + $subscribers = iterator_to_array( $records ); $data = array( 'subscribers' => $subscribers, diff --git a/includes/Rest/Help/Help.php b/includes/Rest/Help/Help.php index 0477ec17..d1d0dea8 100644 --- a/includes/Rest/Help/Help.php +++ b/includes/Rest/Help/Help.php @@ -7,6 +7,7 @@ use WeDevs\WeMail\RestController; use WeDevs\WeMail\Core\Help\SystemInfo; use WP_REST_Server; +use WP_User_Query; class Help extends RestController { @@ -60,6 +61,17 @@ public function register_routes() { ), ) ); + register_rest_route( + $this->namespace, + $this->rest_base . '/admin/users', + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'users' ), + 'permission_callback' => array( $this, 'permission' ), + ), + ) + ); } /** @@ -112,4 +124,37 @@ public function disconnect_wemail() { ) ); } + + public function users() { + $args = array( + 'role' => 'administrator', + ); + + $users = get_users( $args ); + + $emails = array_map( + function ( $user ) { + return $user->user_email; + }, + $users + ); + + return rest_ensure_response( $emails ); + } + + public function permission( $request ) { + $api_key = $request->get_header( 'X-WeMail-Key' ); + + if ( ! empty( $api_key ) ) { + $query = new WP_User_Query( + array( + 'fields' => 'ID', + 'meta_key' => 'wemail_api_key', + 'meta_value' => $api_key, + ) + ); + return (bool) $query->get_total(); + } + return false; + } } diff --git a/includes/Rest/Remote.php b/includes/Rest/Remote.php new file mode 100644 index 00000000..da9e27b6 --- /dev/null +++ b/includes/Rest/Remote.php @@ -0,0 +1,76 @@ +post( '/', 'call_remote', 'manage_options' ); + } + + /** + * Recursively sanitize input data (array/object/string) + */ + private function wemail_recursive_sanitize( $data ) { + if ( is_array( $data ) ) { + foreach ( $data as $key => $value ) { + $data[ $key ] = $this->wemail_recursive_sanitize( $value ); + } + return $data; + } elseif ( is_bool( $data ) ) { + return $data; + } elseif ( is_email( $data ) ) { + return sanitize_email( $data ); + } elseif ( is_numeric( $data ) ) { + return absint( $data ); + } elseif ( filter_var( $data, FILTER_VALIDATE_URL ) ) { + return esc_url_raw( $data ); + } else { + return sanitize_text_field( $data ); + } + } + + /** + * Call remote api | weMail api + * This is proxy to call weMail api + * + * @since 2.0.0 + * + * @param \WP_REST_Request $request + * + * @return \WP_REST_Response|mixed + */ + public function call_remote( $request ) { + $url = esc_url_raw( $request->get_param( 'url' ) ); + $method = strtolower( sanitize_text_field( $request->get_param( 'method' ) ) ); + + $data = $request->get_param( 'data' ); + if ( is_array( $data ) ) { + $data = $this->wemail_recursive_sanitize( $data ); + } + + $query = $request->get_param( 'query' ); + if ( is_array( $query ) ) { + $query = $this->wemail_recursive_sanitize( $query ); + } + + $wemail_api_base = wemail()->wemail_api; + $path = str_replace( $wemail_api_base, '', $url ); + + if ( $method === 'get' ) { + $response = wemail()->api->send_json()->get( $path, $query ); + } else { + $data = array_merge( $data ? $data : array(), $query ? $query : array() ); + $response = wemail()->api->url( $path )->send_json()->{$method}( $data, array() ); + } + + return $response; + } +} diff --git a/includes/Rest/Rest.php b/includes/Rest/Rest.php index 633d1036..1c5cf1f5 100644 --- a/includes/Rest/Rest.php +++ b/includes/Rest/Rest.php @@ -35,5 +35,6 @@ public function register_controllers() { new Ecommerce(); new Help(); new AffiliateIntegrations(); + new Remote(); } } diff --git a/includes/Rest/Users.php b/includes/Rest/Users.php index 967c409d..8df2adfb 100644 --- a/includes/Rest/Users.php +++ b/includes/Rest/Users.php @@ -53,15 +53,15 @@ function ( $user ) { } public function storeRoles( $request ) { - $roles = $this->saveAccessibleRoles($request); - $access_token = get_option('wemail_api_key'); + $roles = $this->saveAccessibleRoles( $request ); + $access_token = get_option( 'wemail_api_key' ); - if (empty($roles) || !is_array($roles)) { - return $this->respond(array('message' => 'Invalid roles provided'), 422); + if ( empty( $roles ) || ! is_array( $roles ) ) { + return $this->respond( array( 'message' => 'Invalid roles provided' ), 422 ); } - if (empty($access_token)) { - return $this->respond(array('message' => 'API token not available'), 422); + if ( empty( $access_token ) ) { + return $this->respond( array( 'message' => 'API token not available' ), 422 ); } $data = array( @@ -69,13 +69,13 @@ public function storeRoles( $request ) { 'api_token' => $access_token, ); - $response = wemail()->api->wp()->users()->rolePermissions()->post($data); + $response = wemail()->api->wp()->users()->rolePermissions()->post( $data ); - if ($response['success'] === true) { - return $this->respond(array('message' => $response['message']), 200); + if ( $response['success'] === true ) { + return $this->respond( array( 'message' => $response['message'] ), 200 ); } - return $this->respond(array('message' => 'Failed to update roles'), 422); + return $this->respond( array( 'message' => 'Failed to update roles' ), 422 ); } public function update( $request ) { @@ -183,8 +183,8 @@ public function store( $request ) { $users = get_users( $args ); - foreach ($users as $user) { - delete_user_meta($user->ID, 'wemail_user_data'); + foreach ( $users as $user ) { + delete_user_meta( $user->ID, 'wemail_user_data' ); } return $this->respond( array( 'success' => true ), 200 ); @@ -194,11 +194,10 @@ public function store( $request ) { * @param $request * @return mixed */ - public function saveAccessibleRoles($request) - { - $roles = $request->get_param('roles'); + public function saveAccessibleRoles( $request ) { + $roles = $request->get_param( 'roles' ); - update_option('wemail_accessible_roles', $roles); + update_option( 'wemail_accessible_roles', $roles ); return $roles; } } diff --git a/includes/WeMail.php b/includes/WeMail.php index 7d8126ed..bf5ba766 100644 --- a/includes/WeMail.php +++ b/includes/WeMail.php @@ -23,7 +23,7 @@ final class WeMail { * * @var string */ - public $version = '1.14.12'; + public $version = '1.14.15'; /** * DB version diff --git a/package.json b/package.json index 97a5781c..7ffe30da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wemail", - "version": "1.14.12", + "version": "1.14.15", "description": "Send Beautiful Email Newsletters with WordPress", "scripts": { "build": "node build", diff --git a/readme.txt b/readme.txt index 3da96f41..93aa5cc1 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Donate link: https://getwemail.io Tags: email marketing, newsletter, subscription, smtp, optins Requires at least: 5.6 Tested up to: 6.7.2 -Stable tag: 1.14.12 +Stable tag: 1.14.15 Requires PHP: 7.4 License: GPLv2 or later License URL: https://www.gnu.org/licenses/gpl-2.0.html @@ -274,6 +274,15 @@ emails. == Changelog == += v1.14.15 - (23rd June, 2025) = +* **Fix** Resolved CSV import issues on PHP 8.1 and 8.2. + += v1.14.14 - (25th Apr, 2025) = +* **Fix** Fix vulnerability issue for access admin user + += v1.14.13 - (15th Apr, 2025) = +* **Enhancement**: Added functionality to send transaction disable notification emails to all admin users, with a compatibility layer for both updated and legacy plugin versions + = v1.14.12 - (5th Mar, 2025) = * Updated tested up to WordPress 5.6 or higher * Updated tested up to PHP 7.4 or higher diff --git a/wemail.php b/wemail.php index b420edf6..1a74373f 100644 --- a/wemail.php +++ b/wemail.php @@ -6,7 +6,7 @@ * Plugin URI: https://wordpress.org/plugins/wemail/ * Author: weDevs * Author URI: https://getwemail.io/?utm_source=wp-org&utm_medium=author-uri - * Version: 1.14.12 + * Version: 1.14.15 * License: GPL-3.0 * License URI: https://www.gnu.org/licenses/gpl-2.0.html * Text Domain: wemail