$response->errors['http_request_failed'] ) ), $debugging_information ); } if ( 200 !== $response_code && ! empty( $response_message ) ) { return new WP_Error( $response_code, $response_message, $debugging_information ); } elseif ( 200 !== $response_code ) { return new WP_Error( $response_code, __( 'An unknown API error occurred.', 'envato-market' ), $debugging_information ); } else { $return = json_decode( wp_remote_retrieve_body( $response ), true ); if ( null === $return ) { return new WP_Error( 'api_error', __( 'An unknown API error occurred.', 'envato-market' ), $debugging_information ); } return $return; } } /** * Deferred item download URL. * * @since 1.0.0 * * @param int $id The item ID. * @return string. */ public function deferred_download( $id ) { if ( empty( $id ) ) { return ''; } $args = array( 'deferred_download' => true, 'item_id' => $id, ); return add_query_arg( $args, esc_url( envato_market()->get_page_url() ) ); } /** * Get the item download. * * @since 1.0.0 * * @param int $id The item ID. * @param array $args The arguments passed to `wp_remote_get`. * @return bool|array The HTTP response. */ public function download( $id, $args = array() ) { if ( empty( $id ) ) { return false; } $url = 'https://api.envato.com/v2/market/buyer/download?item_id=' . $id . '&shorten_url=true'; $response = $this->request( $url, $args ); // @todo Find out which errors could be returned & handle them in the UI. if ( is_wp_error( $response ) || empty( $response ) || ! empty( $response['error'] ) ) { return false; } if ( ! empty( $response['wordpress_theme'] ) ) { return $response['wordpress_theme']; } if ( ! empty( $response['wordpress_plugin'] ) ) { return $response['wordpress_plugin']; } // Missing a WordPress theme and plugin, report an error. $option = envato_market()->get_options(); if ( ! isset( $option['notices'] ) ) { $option['notices'] = []; } $option['notices']['missing-package-zip'] = true; envato_market()->set_options( $option ); return false; } /** * Get an item by ID and type. * * @since 1.0.0 * * @param int $id The item ID. * @param array $args The arguments passed to `wp_remote_get`. * @return array The HTTP response. */ public function item( $id, $args = array() ) { $url = 'https://api.envato.com/v2/market/catalog/item?id=' . $id; $response = $this->request( $url, $args ); if ( is_wp_error( $response ) || empty( $response ) ) { return false; } if ( ! empty( $response['wordpress_theme_metadata'] ) ) { return $this->normalize_theme( $response ); } if ( ! empty( $response['wordpress_plugin_metadata'] ) ) { return $this->normalize_plugin( $response ); } return false; } /** * Get the list of available themes. * * @since 1.0.0 * * @param array $args The arguments passed to `wp_remote_get`. * @return array The HTTP response. */ public function themes( $args = array() ) { $themes = array(); $url = 'https://api.envato.com/v2/market/buyer/list-purchases?filter_by=wordpress-themes'; $response = $this->request( $url, $args ); if ( is_wp_error( $response ) || empty( $response ) || empty( $response['results'] ) ) { return $themes; } foreach ( $response['results'] as $theme ) { $themes[] = $this->normalize_theme( $theme['item'] ); } return $themes; } /** * Normalize a theme. * * @since 1.0.0 * * @param array $theme An array of API request values. * @return array A normalized array of values. */ public function normalize_theme( $theme ) { $normalized_theme = array( 'id' => $theme['id'], 'name' => ( ! empty( $theme['wordpress_theme_metadata']['theme_name'] ) ? $theme['wordpress_theme_metadata']['theme_name'] : '' ), 'author' => ( ! empty( $theme['wordpress_theme_metadata']['author_name'] ) ? $theme['wordpress_theme_metadata']['author_name'] : '' ), 'version' => ( ! empty( $theme['wordpress_theme_metadata']['version'] ) ? $theme['wordpress_theme_metadata']['version'] : '' ), 'description' => self::remove_non_unicode( strip_tags( $theme['wordpress_theme_metadata']['description'] ) ), 'url' => ( ! empty( $theme['url'] ) ? $theme['url'] : '' ), 'author_url' => ( ! empty( $theme['author_url'] ) ? $theme['author_url'] : '' ), 'thumbnail_url' => ( ! empty( $theme['thumbnail_url'] ) ? $theme['thumbnail_url'] : '' ), 'rating' => ( ! empty( $theme['rating'] ) ? $theme['rating'] : '' ), 'landscape_url' => '', ); // No main thumbnail in API response, so we grab it from the preview array. if ( empty( $normalized_theme['thumbnail_url'] ) && ! empty( $theme['previews'] ) && is_array( $theme['previews'] ) ) { foreach ( $theme['previews'] as $possible_preview ) { if ( ! empty( $possible_preview['landscape_url'] ) ) { $normalized_theme['landscape_url'] = $possible_preview['landscape_url']; break; } } } if ( empty( $normalized_theme['thumbnail_url'] ) && ! empty( $theme['previews'] ) && is_array( $theme['previews'] ) ) { foreach ( $theme['previews'] as $possible_preview ) { if ( ! empty( $possible_preview['icon_url'] ) ) { $normalized_theme['thumbnail_url'] = $possible_preview['icon_url']; break; } } } return $normalized_theme; } /** * Get the list of available plugins. * * @since 1.0.0 * * @param array $args The arguments passed to `wp_remote_get`. * @return array The HTTP response. */ public function plugins( $args = array() ) { $plugins = array(); $url = 'https://api.envato.com/v2/market/buyer/list-purchases?filter_by=wordpress-plugins'; $response = $this->request( $url, $args ); if ( is_wp_error( $response ) || empty( $response ) || empty( $response['results'] ) ) { return $plugins; } foreach ( $response['results'] as $plugin ) { $plugins[] = $this->normalize_plugin( $plugin['item'] ); } return $plugins; } /** * Normalize a plugin. * * @since 1.0.0 * * @param array $plugin An array of API request values. * @return array A normalized array of values. */ public function normalize_plugin( $plugin ) { $requires = null; $tested = null; $versions = array(); // Set the required and tested WordPress version numbers. foreach ( $plugin['attributes'] as $k => $v ) { if ( ! empty( $v['name'] ) && 'compatible-software' === $v['name'] && ! empty( $v['value'] ) && is_array( $v['value'] ) ) { foreach ( $v['value'] as $version ) { $versions[] = str_replace( 'WordPress ', '', trim( $version ) ); } if ( ! empty( $versions ) ) { $requires = $versions[ count( $versions ) - 1 ]; $tested = $versions[0]; } break; } } $plugin_normalized = array( 'id' => $plugin['id'], 'name' => ( ! empty( $plugin['wordpress_plugin_metadata']['plugin_name'] ) ? $plugin['wordpress_plugin_metadata']['plugin_name'] : '' ), 'author' => ( ! empty( $plugin['wordpress_plugin_metadata']['author'] ) ? $plugin['wordpress_plugin_metadata']['author'] : '' ), 'version' => ( ! empty( $plugin['wordpress_plugin_metadata']['version'] ) ? $plugin['wordpress_plugin_metadata']['version'] : '' ), 'description' => self::remove_non_unicode( strip_tags( $plugin['wordpress_plugin_metadata']['description'] ) ), 'url' => ( ! empty( $plugin['url'] ) ? $plugin['url'] : '' ), 'author_url' => ( ! empty( $plugin['author_url'] ) ? $plugin['author_url'] : '' ), 'thumbnail_url' => ( ! empty( $plugin['thumbnail_url'] ) ? $plugin['thumbnail_url'] : '' ), 'landscape_url' => ( ! empty( $plugin['previews']['landscape_preview']['landscape_url'] ) ? $plugin['previews']['landscape_preview']['landscape_url'] : '' ), 'requires' => $requires, 'tested' => $tested, 'number_of_sales' => ( ! empty( $plugin['number_of_sales'] ) ? $plugin['number_of_sales'] : '' ), 'updated_at' => ( ! empty( $plugin['updated_at'] ) ? $plugin['updated_at'] : '' ), 'rating' => ( ! empty( $plugin['rating'] ) ? $plugin['rating'] : '' ), ); // No main thumbnail in API response, so we grab it from the preview array. if ( empty( $plugin_normalized['landscape_url'] ) && ! empty( $plugin['previews'] ) && is_array( $plugin['previews'] ) ) { foreach ( $plugin['previews'] as $possible_preview ) { if ( ! empty( $possible_preview['landscape_url'] ) ) { $plugin_normalized['landscape_url'] = $possible_preview['landscape_url']; break; } } } if ( empty( $plugin_normalized['thumbnail_url'] ) && ! empty( $plugin['previews'] ) && is_array( $plugin['previews'] ) ) { foreach ( $plugin['previews'] as $possible_preview ) { if ( ! empty( $possible_preview['icon_url'] ) ) { $plugin_normalized['thumbnail_url'] = $possible_preview['icon_url']; break; } } } return $plugin_normalized; } /** * Remove all non unicode characters in a string * * @since 1.0.0 * * @param string $retval The string to fix. * @return string */ static private function remove_non_unicode( $retval ) { return preg_replace( '/[\x00-\x1F\x80-\xFF]/', '', $retval ); } } endif; g state/county', 'mailpoet'), function (OrderPayload $payload) { return $payload->getOrder()->get_shipping_state(); } ), new Field( 'woocommerce:order:shipping-country', Field::TYPE_ENUM, __('Shipping country', 'mailpoet'), function (OrderPayload $payload) { return $payload->getOrder()->get_shipping_country(); }, [ 'options' => $this->getShippingCountryOptions(), ] ), new Field( 'woocommerce:order:created-date', Field::TYPE_DATETIME, __('Created date', 'mailpoet'), function (OrderPayload $payload) { return $payload->getOrder()->get_date_created(); } ), new Field( 'woocommerce:order:paid-date', Field::TYPE_DATETIME, __('Paid date', 'mailpoet'), function (OrderPayload $payload) { return $payload->getOrder()->get_date_paid(); } ), new Field( 'woocommerce:order:customer-note', Field::TYPE_STRING, __('Customer provided note', 'mailpoet'), function (OrderPayload $payload) { return $payload->getOrder()->get_customer_note(); } ), new Field( 'woocommerce:order:payment-method', Field::TYPE_ENUM, __('Payment method', 'mailpoet'), function (OrderPayload $payload) { return $payload->getOrder()->get_payment_method(); }, [ 'options' => $this->getOrderPaymentOptions(), ] ), new Field( 'woocommerce:order:status', Field::TYPE_ENUM, __('Status', 'mailpoet'), function (OrderPayload $payload) { return $payload->getOrder()->get_status(); }, [ 'options' => $this->getOrderStatusOptions(), ] ), new Field( 'woocommerce:order:total', Field::TYPE_NUMBER, __('Total', 'mailpoet'), function (OrderPayload $payload) { return (float)$payload->getOrder()->get_total(); } ), new Field( 'woocommerce:order:coupons', Field::TYPE_ENUM_ARRAY, __('Used coupons', 'mailpoet'), function (OrderPayload $payload) { return $payload->getOrder()->get_coupon_codes(); }, [ 'options' => $this->getCouponOptions(), ] ), new Field( 'woocommerce:order:is-first-order', Field::TYPE_BOOLEAN, __('Is first order', 'mailpoet'), function (OrderPayload $payload) { $order = $payload->getOrder(); return !$this->previousOrderExists($order); } ), new Field( 'woocommerce:order:categories', Field::TYPE_ENUM_ARRAY, __('Categories', 'mailpoet'), function (OrderPayload $payload) { $products = $this->getProducts($payload->getOrder()); $categoryIds = []; foreach ($products as $product) { $categoryIds = array_merge($categoryIds, $product->get_category_ids()); } $categoryIds = array_merge($categoryIds, $this->termParentsLoader->getParentIds($categoryIds)); sort($categoryIds); return array_unique($categoryIds); }, [ 'options' => $this->termOptionsBuilder->getTermOptions('product_cat'), ] ), new Field( 'woocommerce:order:tags', Field::TYPE_ENUM_ARRAY, __('Tags', 'mailpoet'), function (OrderPayload $payload) { $products = $this->getProducts($payload->getOrder()); $tagIds = []; foreach ($products as $product) { $tagIds = array_merge($tagIds, $product->get_tag_ids()); } sort($tagIds); return array_unique($tagIds); }, [ 'options' => $this->termOptionsBuilder->getTermOptions('product_tag'), ] ), new Field( 'woocommerce:order:products', Field::TYPE_ENUM_ARRAY, __('Products', 'mailpoet'), function (OrderPayload $payload) { $products = $this->getProducts($payload->getOrder()); return array_map(function (WC_Product $product) { return $product->get_id(); }, $products); }, [ 'options' => $this->getProductOptions(), ] ), ] ); } private function getBillingCountryOptions(): array { $options = []; foreach (WC()->countries->get_allowed_countries() as $code => $name) { $options[] = ['id' => $code, 'name' => $name]; } return $options; } private function getShippingCountryOptions(): array { $options = []; foreach (WC()->countries->get_shipping_countries() as $code => $name) { $options[] = ['id' => $code, 'name' => $name]; } return $options; } private function getOrderPaymentOptions(): array { $gateways = WC()->payment_gateways()->get_available_payment_gateways(); $options = []; foreach ($gateways as $gateway) { if ($gateway instanceof WC_Payment_Gateway && $gateway->enabled === 'yes') { $options[] = ['id' => $gateway->id, 'name' => $gateway->title]; } } return $options; } private function getOrderStatusOptions(): array { $statuses = $this->wooCommerce->wcGetOrderStatuses(); $options = []; foreach ($statuses as $id => $name) { $options[] = [ 'id' => substr($id, 0, 3) === 'wc-' ? substr($id, 3) : $id, 'name' => $name, ]; } return $options; } private function getCouponOptions(): array { $coupons = $this->wordPress->getPosts([ 'post_type' => 'shop_coupon', 'post_status' => 'publish', 'posts_per_page' => -1, 'orderby' => 'name', 'order' => 'asc', ]); $options = []; foreach ($coupons as $coupon) { if ($coupon instanceof WP_Post) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps $options[] = ['id' => $coupon->post_title, 'name' => $coupon->post_title]; } } return $options; } private function previousOrderExists(WC_Order $order): bool { $dateCreated = $order->get_date_created() ?? new DateTimeImmutable('now', $this->wordPress->wpTimezone()); $query = [ 'date_created' => '<=' . $dateCreated->getTimestamp(), 'limit' => 2, 'return' => 'ids', ]; if ($order->get_customer_id() > 0) { $query['customer_id'] = $order->get_customer_id(); } else { $query['billing_email'] = $order->get_billing_email(); } $orderIds = (array)$this->wooCommerce->wcGetOrders($query); return count($orderIds) > 1 && min($orderIds) < $order->get_id(); } /** @return WC_Product[] */ private function getProducts(WC_Order $order): array { $products = []; foreach ($order->get_items() as $item) { if (!$item instanceof WC_Order_Item_Product) { continue; } $product = $item->get_product(); if ($product instanceof WC_Product) { $products[] = $product; } } return array_unique($products); } private function getProductOptions(): array { $wpdb = $this->wordPress->getWpdb(); $products = $wpdb->get_results( " SELECT ID, post_title FROM {$wpdb->posts} WHERE post_type = 'product' AND post_status = 'publish' ORDER BY post_title ASC ", ARRAY_A ); return array_map(function ($product) { $id = $product['ID']; $title = $product['post_title']; return ['id' => (int)$id, 'name' => "$title (#$id)"]; }, (array)$products); } }
Fatal error: Uncaught Error: Class "MailPoet\Automation\Integrations\WooCommerce\Fields\OrderFieldsFactory" not found in /htdocs/wp-content/plugins/mailpoet/generated/FreeCachedContainer.php:2038 Stack trace: #0 /htdocs/wp-content/plugins/mailpoet/generated/FreeCachedContainer.php(2164): MailPoetGenerated\FreeCachedContainer->getOrderFieldsFactoryService() #1 /htdocs/wp-content/plugins/mailpoet/generated/FreeCachedContainer.php(2276): MailPoetGenerated\FreeCachedContainer->getWooCommerceIntegrationService() #2 /htdocs/wp-content/plugins/mailpoet/vendor-prefixed/symfony/dependency-injection/Container.php(122): MailPoetGenerated\FreeCachedContainer->getInitializerService() #3 /htdocs/wp-content/plugins/mailpoet/vendor-prefixed/symfony/dependency-injection/Container.php(110): MailPoetVendor\Symfony\Component\DependencyInjection\Container->make('MailPoet\\Config...', 1) #4 /htdocs/wp-content/plugins/mailpoet/lib/DI/ContainerWrapper.php(39): MailPoetVendor\Symfony\Component\DependencyInjection\Container->get('MailPoet\\Config...') #5 /htdocs/wp-content/plugins/mailpoet/mailpoet_initializer.php(89): MailPoet\DI\ContainerWrapper->get('MailPoet\\Config...') #6 /htdocs/wp-content/plugins/mailpoet/mailpoet.php(206): require_once('/htdocs/wp-cont...') #7 /htdocs/wp-settings.php(462): include_once('/htdocs/wp-cont...') #8 /htdocs/wp-config.php(96): require_once('/htdocs/wp-sett...') #9 /htdocs/wp-load.php(50): require_once('/htdocs/wp-conf...') #10 /htdocs/wp-blog-header.php(13): require_once('/htdocs/wp-load...') #11 /htdocs/index.php(17): require('/htdocs/wp-blog...') #12 {main} thrown in /htdocs/wp-content/plugins/mailpoet/generated/FreeCachedContainer.php on line 2038