| @@ -11,11 +11,12 @@ | ||
| 11 | 11 | |
| 12 | 12 | namespace Parsely\UI; |
| 13 | 13 | |
| 14 | 14 | use Parsely\Parsely; |
| 15 | -use Parsely\Utils\Utils; | |
| 16 | 15 | use WP_Widget; |
| 17 | 16 | |
| 17 | +use function Parsely\Utils\get_asset_info; | |
| 18 | + | |
| 18 | 19 | use const Parsely\PARSELY_FILE; |
| 19 | 20 | |
| 20 | 21 | /** |
| 21 | 22 | * Provides a widget with Parse.ly recommended articles. |
| @@ -25,8 +26,9 @@ | ||
| 25 | 26 | * return_limit: int, |
| 26 | 27 | * display_direction: string, |
| 27 | 28 | * published_within: int, |
| 28 | 29 | * sort: string, |
| 30 | + * boost: string, | |
| 29 | 31 | * personalize_results: bool, |
| 30 | 32 | * img_src: string, |
| 31 | 33 | * display_author: bool, |
| 32 | 34 | * } |
| @@ -49,8 +51,9 @@ | ||
| 49 | 51 | 'return_limit' => 5, |
| 50 | 52 | 'display_direction' => 'vertical', |
| 51 | 53 | 'published_within' => 0, |
| 52 | 54 | 'sort' => 'score', |
| 55 | + 'boost' => 'views', | |
| 53 | 56 | 'personalize_results' => false, |
| 54 | 57 | 'img_src' => 'parsely_thumb', |
| 55 | 58 | 'display_author' => false, |
| 56 | 59 | ); |
| @@ -75,25 +78,27 @@ | ||
| 75 | 78 | |
| 76 | 79 | /** |
| 77 | 80 | * Gets the URL for the Recommendations API (GET /related). |
| 78 | 81 | * |
| 79 | - * @since 2.5.0 | |
| 82 | + * @see https://www.parse.ly/help/api/recommendations#get-related | |
| 80 | 83 | * |
| 81 | - * @see https://docs.parse.ly/content-recommendations/ | |
| 84 | + * @internal While this is a public method now, this should be moved to a new class. | |
| 82 | 85 | * |
| 83 | - * @internal While this is a public method now, this should be moved to a new class. | |
| 86 | + * @since 2.5.0 | |
| 84 | 87 | * |
| 85 | 88 | * @param string $site_id Publisher Site ID. |
| 86 | - * @param int|null $published_within Publication filter start date; see https://docs.parse.ly/api-date-time/ for | |
| 89 | + * @param int|null $published_within Publication filter start date; see https://www.parse.ly/help/api/time for | |
| 87 | 90 | * formatting details. No restriction by default. |
| 88 | 91 | * @param string|null $sort What to sort the results by. There are currently 2 valid options: `score`, |
| 89 | 92 | * which will sort articles by overall relevance and `pub_date` which will sort |
| 90 | 93 | * results by their publication date. The default is `score`. |
| 94 | + * @param string|null $boost Available for sort=score only. Sub-sort value to re-rank relevant posts that | |
| 95 | + * received high e.g. views; default is undefined. | |
| 91 | 96 | * @param int $return_limit Number of records to retrieve; defaults to "10". |
| 92 | 97 | * @return string API URL. |
| 93 | 98 | */ |
| 94 | - private function get_api_url( string $site_id, ?int $published_within, ?string $sort, int $return_limit ): string { | |
| 95 | - $related_api_endpoint = $this->parsely->get_content_api()->get_endpoint( '/related' ); | |
| 99 | + private function get_api_url( string $site_id, ?int $published_within, ?string $sort, ?string $boost, int $return_limit ): string { | |
| 100 | + $related_api_endpoint = Parsely::PUBLIC_API_BASE_URL . '/related'; | |
| 96 | 101 | |
| 97 | 102 | $query_args = array( |
| 98 | 103 | 'apikey' => $site_id, |
| 99 | 104 | 'sort' => $sort, |
| @@ -99,13 +104,17 @@ | ||
| 99 | 104 | 'sort' => $sort, |
| 100 | 105 | 'limit' => $return_limit, |
| 101 | 106 | ); |
| 102 | 107 | |
| 108 | + if ( 'score' === $sort && 'no-boost' !== $boost ) { | |
| 109 | + $query_args['boost'] = $boost; | |
| 110 | + } | |
| 111 | + | |
| 103 | 112 | if ( null !== $published_within && 0 !== $published_within ) { |
| 104 | 113 | $query_args['pub_date_start'] = $published_within . 'd'; |
| 105 | 114 | } |
| 106 | 115 | |
| 107 | - return $related_api_endpoint->get_endpoint_url( $query_args ); | |
| 116 | + return add_query_arg( $query_args, $related_api_endpoint ); | |
| 108 | 117 | } |
| 109 | 118 | |
| 110 | 119 | /** |
| 111 | 120 | * This is the widget function. |
| @@ -135,8 +144,9 @@ | ||
| 135 | 144 | $api_url = $this->get_api_url( |
| 136 | 145 | $this->parsely->get_site_id(), |
| 137 | 146 | (int) $instance['published_within'], // @phpstan-ignore-line |
| 138 | 147 | $instance['sort'], |
| 148 | + $instance['boost'], | |
| 139 | 149 | (int) $instance['return_limit'] // @phpstan-ignore-line |
| 140 | 150 | ); |
| 141 | 151 | |
| 142 | 152 | ?> |
| @@ -152,9 +162,9 @@ | ||
| 152 | 162 | ></div> |
| 153 | 163 | |
| 154 | 164 | <?php |
| 155 | 165 | |
| 156 | - $recommended_widget_script_asset = Utils::get_asset_info( 'build/recommended-widget.asset.php' ); | |
| 166 | + $recommended_widget_script_asset = get_asset_info( 'build/recommended-widget.asset.php' ); | |
| 157 | 167 | |
| 158 | 168 | wp_register_script( |
| 159 | 169 | 'wp-parsely-recommended-widget', |
| 160 | 170 | plugin_dir_url( PARSELY_FILE ) . 'build/recommended-widget.js', |
| @@ -182,9 +192,9 @@ | ||
| 182 | 192 | * @param array<mixed> $current_settings Values saved to the db. |
| 183 | 193 | */ |
| 184 | 194 | public function form( $current_settings ): string { |
| 185 | 195 | if ( ! $this->site_id_and_secret_are_populated() ) { |
| 186 | - $settings_page_url = add_query_arg( 'page', 'parsely-settings', get_admin_url() . 'admin.php' ); | |
| 196 | + $settings_page_url = add_query_arg( 'page', 'parsely', get_admin_url() . 'options-general.php' ); | |
| 187 | 197 | |
| 188 | 198 | $message = sprintf( |
| 189 | 199 | /* translators: %s: Plugin settings page URL */ |
| 190 | 200 | __( 'The <i>Parse.ly Site ID</i> and <i>Parse.ly API Secret</i> fields need to be populated on the <a href="%s">Parse.ly settings page</a> for this widget to work.', 'wp-parsely' ), |
| @@ -203,8 +213,9 @@ | ||
| 203 | 213 | $return_limit = $instance['return_limit']; |
| 204 | 214 | $display_direction = $instance['display_direction']; |
| 205 | 215 | $published_within = $instance['published_within']; |
| 206 | 216 | $sort = $instance['sort']; |
| 217 | + $boost = $instance['boost']; | |
| 207 | 218 | $personalize_results = $instance['personalize_results']; |
| 208 | 219 | $img_src = $instance['img_src']; |
| 209 | 220 | $display_author = $instance['display_author']; |
| 210 | 221 | |
| @@ -211,12 +222,14 @@ | ||
| 211 | 222 | $instance['return_limit'] = $return_limit; |
| 212 | 223 | $instance['display_direction'] = $display_direction; |
| 213 | 224 | $instance['published_within'] = $published_within; |
| 214 | 225 | $instance['sort'] = $sort; |
| 226 | + $instance['boost'] = $boost; | |
| 215 | 227 | $instance['personalize_results'] = $personalize_results; |
| 216 | 228 | $instance['img_src'] = $img_src; |
| 217 | 229 | $instance['display_author'] = $display_author; |
| 218 | 230 | |
| 231 | + $boost_params = $this->get_boost_params(); | |
| 219 | 232 | ?> |
| 220 | 233 | <p> |
| 221 | 234 | <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title:', 'wp-parsely' ); ?></label> |
| 222 | 235 | <br> |
| @@ -247,13 +260,23 @@ | ||
| 247 | 260 | <p> |
| 248 | 261 | <label for="<?php echo esc_attr( $this->get_field_id( 'sort' ) ); ?>"><?php esc_html_e( 'Sort by:', 'wp-parsely' ); ?></label> |
| 249 | 262 | <br> |
| 250 | 263 | <select id="<?php echo esc_attr( $this->get_field_id( 'sort' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'sort' ) ); ?>" class="widefat"> |
| 251 | - <option<?php selected( $instance['sort'], 'score' ); ?> value="score"><?php esc_html_e( 'Score', 'wp-parsely' ); ?></option> | |
| 252 | - <option<?php selected( $instance['sort'], 'pub_date' ); ?> value="pub_date"><?php esc_html_e( 'Publish date', 'wp-parsely' ); ?></option> | |
| 264 | + <option<?php selected( $instance['sort'], 'score' ); ?> value="score"><?php esc_html_e( 'Score (relevancy, boostable)', 'wp-parsely' ); ?></option> | |
| 265 | + <option<?php selected( $instance['sort'], 'pub_date' ); ?> value="pub_date"><?php esc_html_e( 'Publish date (not boostable)', 'wp-parsely' ); ?></option> | |
| 253 | 266 | </select> |
| 254 | 267 | </p> |
| 255 | 268 | <p> |
| 269 | + <label for="<?php echo esc_attr( $this->get_field_id( 'boost' ) ); ?>"><?php esc_html_e( 'Boost by:', 'wp-parsely' ); ?></label> | |
| 270 | + <br> | |
| 271 | + <select id="<?php echo esc_attr( $this->get_field_id( 'boost' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'boost' ) ); ?>" class="widefat"> | |
| 272 | + <?php foreach ( $boost_params as $boost_param => $description ) { ?> | |
| 273 | + <option<?php selected( $instance['boost'], $boost_param ); ?> value="<?php echo esc_attr( $boost_param ); ?>"><?php echo esc_html( $description ); ?></option> | |
| 274 | + <?php } ?> | |
| 275 | + </select> | |
| 276 | + | |
| 277 | + </p> | |
| 278 | + <p> | |
| 256 | 279 | <label for="<?php echo esc_attr( $this->get_field_id( 'img_src' ) ); ?>"><?php esc_html_e( 'Image source:', 'wp-parsely' ); ?></label> |
| 257 | 280 | <br> |
| 258 | 281 | <select id="<?php echo esc_attr( $this->get_field_id( 'img_src' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'img_src' ) ); ?>" class="widefat"> |
| 259 | 282 | <option<?php selected( $instance['img_src'], 'parsely_thumb' ); ?> value="parsely_thumb"><?php esc_html_e( 'Parse.ly generated thumbnail (85x85px)', 'wp-parsely' ); ?></option> |
| @@ -277,8 +300,9 @@ | ||
| 277 | 300 | * This is the update function. |
| 278 | 301 | * |
| 279 | 302 | * @param Widget_Settings $new_instance The new values for the db. |
| 280 | 303 | * @param Widget_Settings $old_instance Values saved to the db. |
| 304 | + * | |
| 281 | 305 | * @return Widget_Settings |
| 282 | 306 | */ |
| 283 | 307 | public function update( $new_instance, $old_instance ) /* @phpstan-ignore-line */ { |
| 284 | 308 | $instance = $old_instance; |
| @@ -286,8 +310,9 @@ | ||
| 286 | 310 | $instance['published_within'] = $new_instance['published_within']; |
| 287 | 311 | $instance['return_limit'] = $new_instance['return_limit'] <= 20 ? $new_instance['return_limit'] : 20; |
| 288 | 312 | $instance['display_direction'] = trim( $new_instance['display_direction'] ); |
| 289 | 313 | $instance['sort'] = trim( $new_instance['sort'] ); |
| 314 | + $instance['boost'] = trim( $new_instance['boost'] ); | |
| 290 | 315 | $instance['display_author'] = $new_instance['display_author']; |
| 291 | 316 | $instance['personalize_results'] = $new_instance['personalize_results']; |
| 292 | 317 | $instance['img_src'] = trim( $new_instance['img_src'] ); |
| 293 | 318 | |
| @@ -294,8 +319,40 @@ | ||
| 294 | 319 | return $instance; |
| 295 | 320 | } |
| 296 | 321 | |
| 297 | 322 | /** |
| 323 | + * Returns the list of boost parameters, values and labels. | |
| 324 | + * | |
| 325 | + * @since 2.5.0 | |
| 326 | + * | |
| 327 | + * @return array<string, string> Boost parameters values and labels. | |
| 328 | + */ | |
| 329 | + private function get_boost_params(): array { | |
| 330 | + return array( | |
| 331 | + 'no-boost' => __( 'No boost', 'wp-parsely' ), | |
| 332 | + 'views' => __( 'Page views', 'wp-parsely' ), | |
| 333 | + 'mobile_views' => __( 'Page views on mobile devices', 'wp-parsely' ), | |
| 334 | + 'tablet_views' => __( 'Page views on tablet devices', 'wp-parsely' ), | |
| 335 | + 'desktop_views' => __( 'Page views on desktop devices', 'wp-parsely' ), | |
| 336 | + 'visitors' => __( 'Unique page visitors, total', 'wp-parsely' ), | |
| 337 | + 'visitors_new' => __( 'New visitors', 'wp-parsely' ), | |
| 338 | + 'visitors_returning' => __( 'Returning visitors', 'wp-parsely' ), | |
| 339 | + 'engaged_minutes' => __( 'Total engagement time in minutes', 'wp-parsely' ), | |
| 340 | + 'avg_engaged' => __( 'Engaged minutes spent by total visitors', 'wp-parsely' ), | |
| 341 | + 'avg_engaged_new' => __( 'Average engaged minutes spent by new visitors', 'wp-parsely' ), | |
| 342 | + 'avg_engaged_returning' => __( 'Average engaged minutes spent by returning visitors', 'wp-parsely' ), | |
| 343 | + 'social_interactions' => __( 'Total social interactions', 'wp-parsely' ), | |
| 344 | + 'fb_interactions' => __( 'Count of Facebook shares, likes, and comments', 'wp-parsely' ), | |
| 345 | + 'tw_interactions' => __( 'Count of Twitter tweets and retweets', 'wp-parsely' ), | |
| 346 | + 'pi_interactions' => __( 'Count of Pinterest pins', 'wp-parsely' ), | |
| 347 | + 'social_referrals' => __( 'Page views where the referrer was any social network', 'wp-parsely' ), | |
| 348 | + 'fb_referrals' => __( 'Page views where the referrer was facebook.com', 'wp-parsely' ), | |
| 349 | + 'tw_referrals' => __( 'Page views where the referrer was twitter.com', 'wp-parsely' ), | |
| 350 | + 'pi_referrals' => __( 'Page views where the referrer was pinterest.com', 'wp-parsely' ), | |
| 351 | + ); | |
| 352 | + } | |
| 353 | + | |
| 354 | + /** | |
| 298 | 355 | * Checks if both the Site ID and API secret settings are populated with |
| 299 | 356 | * non-empty values. |
| 300 | 357 | * |
| 301 | 358 | * @since 2.5.0 |
| @@ -312,8 +369,9 @@ | ||
| 312 | 369 | * |
| 313 | 370 | * @since 3.7.0 |
| 314 | 371 | * |
| 315 | 372 | * @param array<string, mixed> $settings Widget Options. |
| 373 | + * | |
| 316 | 374 | * @return Widget_Settings |
| 317 | 375 | */ |
| 318 | 376 | public function get_widget_settings( array $settings ) { |
| 319 | 377 | /** |