PluginProbe
Parse.ly / 3.24.2
Parse.ly v3.24.2
3.24.3 3.24.2 3.24.1 3.24.0 3.23.7 3.23.6 3.23.5 3.23.4 3.23.3 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.17.0 3.18.0 3.18.1 3.19.0 3.19.1 3.19.2 3.19.3 3.2.0 3.2.1 3.20.0 3.20.1 All 107 releases
wp-parsely / src / content-helper / editor-sidebar / performance-stats / provider.ts

provider.ts in Parse.ly 3.24.2, at src/content-helper/editor-sidebar/performance-stats/provider.ts

173 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * WordPress dependencies
3 */
4 import { select } from '@wordpress/data';
5 import { __, sprintf } from '@wordpress/i18n';
6 import { addQueryArgs } from '@wordpress/url';
7
8 /**
9 * Internal dependencies
10 */
11 import {
12 ContentHelperError,
13 ContentHelperErrorCode,
14 } from '../../common/content-helper-error';
15 import { BaseProvider } from '../../common/providers/base-provider';
16 import { getApiPeriodParams } from '../../common/utils/api';
17 import { Period } from '../../common/utils/constants';
18 import {
19 PerformanceData,
20 PerformanceReferrerData,
21 } from './model';
22
23 /**
24 * Provides current post details data for use in other components.
25 */
26 export class PerformanceStatsProvider extends BaseProvider {
27 private itmSource = 'wp-parsely-content-helper';
28
29 /**
30 * The singleton instance of the PerformanceStatsProvider.
31 *
32 * @since 3.15.0
33 */
34 private static instance: PerformanceStatsProvider;
35
36 /**
37 * Returns the singleton instance of the PerformanceStatsProvider.
38 *
39 * @since 3.15.0
40 *
41 * @return {PerformanceStatsProvider} The singleton instance.
42 */
43 public static getInstance(): PerformanceStatsProvider {
44 if ( ! this.instance ) {
45 this.instance = new PerformanceStatsProvider();
46 }
47 return this.instance;
48 }
49
50 /**
51 * Returns details about the post that is currently being edited within the
52 * WordPress Block Editor.
53 *
54 * @param {Period} period The period for which to fetch data.
55 *
56 * @return {Promise<PerformanceData>} The current post's details.
57 */
58 public async getPerformanceStats( period: Period ): Promise<PerformanceData> {
59 const editor = select( 'core/editor' );
60
61 // Get the current post's status.
62 const currentPostStatus = editor.getEditedPostAttribute( 'status' ) ?? 'draft';
63 const trackableStatuses = window.wpParselyTrackableStatuses ?? [ 'publish' ];
64
65 // We cannot show data for non-published posts that are not in the trackable statuses.
66 if ( ! editor.isCurrentPostPublished() && ! trackableStatuses.includes( currentPostStatus ) ) {
67 return Promise.reject(
68 new ContentHelperError( __(
69 'This post is not published, so its details are unavailable.',
70 'wp-parsely' ), ContentHelperErrorCode.PostIsNotPublished, ''
71 )
72 );
73 }
74
75 // Get post ID.
76 const postID = editor.getCurrentPostId();
77
78 if ( null === postID ) {
79 return Promise.reject(
80 new ContentHelperError( __(
81 "The post's ID returned null.",
82 'wp-parsely' ), ContentHelperErrorCode.PostIsNotPublished
83 )
84 );
85 }
86
87 // Fetch all needed results using our WordPress endpoints.
88 let performanceData, referrerData;
89 try {
90 performanceData = await this.fetchPerformanceDataFromWpEndpoint(
91 period, postID
92 );
93 referrerData = await this.fetchReferrerDataFromWpEndpoint(
94 period, postID, performanceData.views
95 );
96 } catch ( contentHelperError ) {
97 return Promise.reject( contentHelperError );
98 }
99
100 return { ...performanceData, referrers: referrerData };
101 }
102
103 /**
104 * Fetches the performance data for the current post from the WordPress REST
105 * API.
106 *
107 * @param {Period} period The period for which to fetch data.
108 * @param {number} postId The post's ID.
109 *
110 * @return {Promise<PerformanceData> } The current post's details.
111 */
112 private async fetchPerformanceDataFromWpEndpoint(
113 period: Period, postId: number
114 ): Promise<PerformanceData> {
115 const response = await this.fetch<PerformanceData[]>( {
116 path: addQueryArgs(
117 `/wp-parsely/v2/stats/post/${ postId }/details`, {
118 ...getApiPeriodParams( period ),
119 itm_source: this.itmSource,
120 } ),
121 } );
122
123 // No data was returned.
124 if ( response.length === 0 ) {
125 const postTitle = select( 'core/editor' ).getEditedPostAttribute( 'title' ) ?? '';
126 return Promise.reject( new ContentHelperError(
127 sprintf(
128 /* translators: %s: Title of the published post */
129 __( '<strong>%s</strong> has 0 views, or the Parse.ly API returned no data.',
130 'wp-parsely' ), postTitle
131 ), ContentHelperErrorCode.ParselyApiReturnedNoData, ''
132 ) );
133 }
134
135 // Data for multiple URLs was returned.
136 if ( response.length > 1 ) {
137 return Promise.reject( new ContentHelperError(
138 sprintf(
139 /* translators: %d: URL of the published post */
140 __( 'Multiple results were returned for the post %d by the Parse.ly API.',
141 'wp-parsely' ), postId
142 ), ContentHelperErrorCode.ParselyApiReturnedTooManyResults
143 ) );
144 }
145
146 return response[ 0 ];
147 }
148
149 /**
150 * Fetches referrer data for the current post from the WordPress REST API.
151 *
152 * @param {Period} period The period for which to fetch data.
153 * @param {string|number} postId The post's ID.
154 * @param {string} totalViews Total post views (including direct views).
155 *
156 * @return {Promise<PerformanceReferrerData>} The post's referrer data.
157 */
158 private async fetchReferrerDataFromWpEndpoint(
159 period: Period, postId: string|number, totalViews: string
160 ): Promise<PerformanceReferrerData> {
161 const response = await this.fetch<PerformanceReferrerData>( {
162 path: addQueryArgs(
163 `/wp-parsely/v2/stats/post/${ postId }/referrers`, {
164 ...getApiPeriodParams( period ),
165 itm_source: this.itmSource,
166 total_views: totalViews, // Needed to calculate direct views.
167 } ),
168 } );
169
170 return response;
171 }
172 }
173