• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / 214ea3e4c90c3ed6a16a9b290bc7d66b661e7141

06 Aug 2025 05:22PM UTC coverage: 48.669% (+0.6%) from 48.035%
214ea3e4c90c3ed6a16a9b290bc7d66b661e7141

Pull #22478

github

web-flow
Merge 53a5a6280 into 8944ae1f4
Pull Request #22478: Add unit tests for `ai-generator`

9 of 11 new or added lines in 2 files covered. (81.82%)

1 existing line in 1 file now uncovered.

16951 of 34829 relevant lines covered (48.67%)

3.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/ai-generator/user-interface/get-usage-route.php
1
<?php
2
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Needed in the folder structure.
3
namespace Yoast\WP\SEO\AI_Generator\User_Interface;
4

5
use WP_REST_Response;
6
use WPSEO_Addon_Manager;
7
use Yoast\WP\SEO\AI_Authorization\Application\Token_Manager;
8
use Yoast\WP\SEO\AI_HTTP_Request\Application\Request_Handler;
9
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Exceptions\Remote_Request_Exception;
10
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Exceptions\WP_Request_Exception;
11
use Yoast\WP\SEO\AI_HTTP_Request\Domain\Request;
12
use Yoast\WP\SEO\Conditionals\AI_Conditional;
13
use Yoast\WP\SEO\Main;
14
use Yoast\WP\SEO\Routes\Route_Interface;
15

16
/**
17
 * Registers a route to get suggestions from the AI API
18
 *
19
 * @makePublic
20
 *
21
 * @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
22
 */
23
class Get_Usage_Route implements Route_Interface {
24

25
        use Route_Permission_Trait;
26

27
                /**
28
                 *  The namespace for this route.
29
                 *
30
                 * @var string
31
                 */
32
        public const ROUTE_NAMESPACE = Main::API_V1_NAMESPACE;
33

34
        /**
35
         *  The prefix for this route.
36
         *
37
         * @var string
38
         */
39
        public const ROUTE_PREFIX = '/ai_generator/get_usage';
40

41
        /**
42
         * The token manager instance.
43
         *
44
         * @var Token_Manager
45
         */
46
        private $token_manager;
47

48
        /**
49
         * The request handler instance.
50
         *
51
         * @var Request_Handler
52
         */
53
        private $request_handler;
54

55
        /**
56
         * Represents the add-on manager.
57
         *
58
         * @var WPSEO_Addon_Manager
59
         */
60
        private $addon_manager;
61

62
        /**
63
         * Returns the conditionals based in which this loadable should be active.
64
         *
65
         * @return array<string> The conditionals.
66
         */
67
        public static function get_conditionals() {
×
68
                return [ AI_Conditional::class ];
×
69
        }
70

71
        /**
72
         * Class constructor.
73
         *
74
         * @param Token_Manager       $token_manager   The token manager instance.
75
         * @param Request_Handler     $request_handler The request handler instance.
76
         * @param WPSEO_Addon_Manager $addon_manager   The add-on manager instance.
77
         */
78
        public function __construct( Token_Manager $token_manager, Request_Handler $request_handler, WPSEO_Addon_Manager $addon_manager ) {
×
79
                $this->addon_manager   = $addon_manager;
×
80
                $this->token_manager   = $token_manager;
×
81
                $this->request_handler = $request_handler;
×
82
        }
83

84
        /**
85
         * Registers routes with WordPress.
86
         *
87
         * @return void
88
         */
89
        public function register_routes() {
×
90
                \register_rest_route(
×
91
                        self::ROUTE_NAMESPACE,
×
92
                        self::ROUTE_PREFIX,
×
93
                        [
×
94
                                'methods'             => 'POST',
×
95
                                'args'                => [
×
96
                                        'is_woo_product_entity' => [
×
97
                                                'type'        => 'boolean',
×
98
                                                'default'     => false,
×
99
                                        ],
×
100
                                ],
×
101
                                'callback'            => [ $this, 'get_usage' ],
×
102
                                'permission_callback' => [ $this, 'check_permissions' ],
×
103
                        ]
×
104
                );
×
105
        }
106

107
        /**
108
         * Runs the callback that gets the monthly usage of the user.
109
         *
110
         * @param WP_REST_Response $response The response object containing the parameters for the request.
111
         *
112
         * @return WP_REST_Response The response of the callback action.
113
         */
NEW
114
        public function get_usage( $response ): WP_REST_Response {
×
NEW
115
                $is_woo_product_entity = $response->get_param( 'is_woo_product_entity' );
×
UNCOV
116
                $user                  = \wp_get_current_user();
×
117
                try {
118
                        $token           = $this->token_manager->get_or_request_access_token( $user );
×
119
                        $request_headers = [
×
120
                                'Authorization' => "Bearer $token",
×
121
                        ];
×
122
                        $action_path     = $this->get_action_path( $is_woo_product_entity );
×
123
                        $response        = $this->request_handler->handle( new Request( $action_path, [], $request_headers, false ) );
×
124
                        $data            = \json_decode( $response->get_body() );
×
125

126
                }  catch ( Remote_Request_Exception | WP_Request_Exception $e ) {
×
127
                        $message = [
×
128
                                'errorMessage'    => $e->getMessage(),
×
129
                                'errorIdentifier' => $e->get_error_identifier(),
×
130
                                'errorCode'       => $e->getCode(),
×
131
                        ];
×
132
                        return new WP_REST_Response(
×
133
                                $message,
×
134
                                $e->getCode()
×
135
                        );
×
136
                }
137

138
                return new WP_REST_Response( $data );
×
139
        }
140

141
        /**
142
         * Get action path for the request.
143
         *
144
         * @param bool $is_woo_product_entity Whether the request is for a WooCommerce product entity.
145
         *
146
         * @return string The action path.
147
         */
148
        public function get_action_path( $is_woo_product_entity = false ): string {
×
149
                $unlimited = '/usage/' . \gmdate( 'Y-m' );
×
150
                if ( $is_woo_product_entity && $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::WOOCOMMERCE_SLUG ) ) {
×
151
                        return $unlimited;
×
152
                }
153
                if ( ! $is_woo_product_entity && $this->addon_manager->has_valid_subscription( WPSEO_Addon_Manager::PREMIUM_SLUG ) ) {
×
154
                        return $unlimited;
×
155
                }
156
                return '/usage/free-usages';
×
157
        }
158
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc