PluginProbe
Tiered Pricing Table for WooCommerce / 2.2.3
Tiered Pricing Table for WooCommerce v2.2.3
8.0.2 7.1.7 7.1.5 7.1.4 7.1.1 6.5.0 6.4.0 6.1.0 trunk 1.0 1.1 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 2.3.1 2.3.2 2.3.3 All 91 releases
← All changes | freemius/templates/add-ons.php +260 -16 2.2.1 → 2.2.3 View file →
@@ -28,9 +28,18 @@
28 28 $addons = $fs->get_addons();
29 29
30 30 $has_addons = ( is_array( $addons ) && 0 < count( $addons ) );
31 31
32 + $account_addon_ids = $fs->get_updated_account_addons();
33 +
34 + $download_latest_text = fs_text_x_inline( 'Download Latest', 'as download latest version', 'download-latest', $slug );
35 + $view_details_text = fs_text_inline( 'View details', 'view-details', $slug );
36 +
32 37 $has_tabs = $fs->_add_tabs_before_content();
38 +
39 + $fs_blog_id = ( is_multisite() && ! is_network_admin() ) ?
40 + get_current_blog_id() :
41 + 0;
33 42 ?>
34 43 <div id="fs_addons" class="wrap fs-section">
35 44 <?php if ( ! $has_tabs ) : ?>
36 45 <h2><?php echo esc_html( sprintf( fs_text_inline( 'Add Ons for %s', 'add-ons-for-x', $slug ), $fs->get_plugin_name() ) ) ?></h2>
@@ -35,8 +44,10 @@
35 44 <?php if ( ! $has_tabs ) : ?>
36 45 <h2><?php echo esc_html( sprintf( fs_text_inline( 'Add Ons for %s', 'add-ons-for-x', $slug ), $fs->get_plugin_name() ) ) ?></h2>
37 46 <?php endif ?>
38 47
48 + <?php $fs->do_action( 'addons/after_title' ) ?>
49 +
39 50 <div id="poststuff">
40 51 <?php if ( ! $has_addons ) : ?>
41 52 <h3><?php echo esc_html( sprintf(
42 53 '%s... %s',
@@ -45,10 +56,27 @@
45 56 ) ) ?></h3>
46 57 <?php endif ?>
47 58 <ul class="fs-cards-list">
48 59 <?php if ( $has_addons ) : ?>
60 + <?php
61 + $plans_and_pricing_by_addon_id = $fs->_get_addons_plans_and_pricing_map_by_id();
62 +
63 + $active_plugins_directories_map = Freemius::get_active_plugins_directories_map( $fs_blog_id );
64 + ?>
49 65 <?php foreach ( $addons as $addon ) : ?>
50 66 <?php
67 + $basename = $fs->get_addon_basename( $addon->id );
68 +
69 + $is_addon_installed = file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $basename ) );
70 + $is_addon_activated = $is_addon_installed ?
71 + $fs->is_addon_activated( $addon->id ) :
72 + false;
73 +
74 + $is_plugin_active = (
75 + $is_addon_activated ||
76 + isset( $active_plugins_directories_map[ dirname( $basename ) ] )
77 + );
78 +
51 79 $open_addon = ( $open_addon || ( $open_addon_slug === $addon->slug ) );
52 80
53 81 $price = 0;
54 82 $has_trial = false;
@@ -54,11 +82,10 @@
54 82 $has_trial = false;
55 83 $has_free_plan = false;
56 84 $has_paid_plan = false;
57 85
58 - $result = $fs->get_api_plugin_scope()->get( $fs->add_show_pending( "/addons/{$addon->id}/pricing.json?type=visible" ) );
59 - if ( ! isset( $result->error ) ) {
60 - $plans = $result->plans;
86 + if ( isset( $plans_and_pricing_by_addon_id[$addon->id] ) ) {
87 + $plans = $plans_and_pricing_by_addon_id[$addon->id];
61 88
62 89 if ( is_array( $plans ) && 0 < count( $plans ) ) {
63 90 foreach ( $plans as $plan ) {
64 91 if ( ! isset( $plan->pricing ) ||
@@ -96,14 +123,34 @@
96 123 }
97 124 ?>
98 125 <li class="fs-card fs-addon" data-slug="<?php echo $addon->slug ?>">
99 126 <?php
100 - echo sprintf( '<a href="%s" class="thickbox fs-overlay" aria-label="%s" data-title="%s"></a>',
101 - esc_url( network_admin_url( 'plugin-install.php?fs_allow_updater_and_dialog=true&tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon->slug .
127 + $view_details_link = sprintf( '<a href="%s" aria-label="%s" data-title="%s"',
128 + esc_url( network_admin_url( 'plugin-install.php?fs_allow_updater_and_dialog=true' . ( ! empty( $fs_blog_id ) ? '&fs_blog_id=' . $fs_blog_id : '' ) . '&tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon->slug .
102 129 '&TB_iframe=true&width=600&height=550' ) ),
103 130 esc_attr( sprintf( fs_text_inline( 'More information about %s', 'more-information-about-x', $slug ), $addon->title ) ),
104 131 esc_attr( $addon->title )
105 - );
132 + ) . ' class="thickbox%s">%s</a>';
133 +
134 + echo sprintf(
135 + $view_details_link,
136 + /**
137 + * Additional class.
138 + *
139 + * @author Leo Fajardo (@leorw)
140 + * @since 2.2.4
141 + */
142 + ' fs-overlay',
143 + /**
144 + * Set the view details link text to an empty string since it is an overlay that
145 + * doesn't really need a text and whose purpose is to open the details dialog when
146 + * the card is clicked.
147 + *
148 + * @author Leo Fajardo (@leorw)
149 + * @since 2.2.4
150 + */
151 + ''
152 + );
106 153 ?>
107 154 <?php
108 155 if ( is_null( $addon->info ) ) {
109 156 $addon->info = new stdClass();
@@ -117,9 +164,19 @@
117 164 ?>
118 165 <div class="fs-inner">
119 166 <ul>
120 167 <li class="fs-card-banner"
121 - style="background-image: url('<?php echo $addon->info->card_banner_url ?>');"></li>
168 + style="background-image: url('<?php echo $addon->info->card_banner_url ?>');"><?php
169 + if ( $is_plugin_active || $is_addon_installed ) {
170 + echo sprintf(
171 + '<span class="fs-badge fs-installed-addon-badge">%s</span>',
172 + esc_html( $is_plugin_active ?
173 + fs_text_x_inline( 'Active', 'active add-on', 'active-addon', $slug ) :
174 + fs_text_x_inline( 'Installed', 'installed add-on', 'installed-addon', $slug )
175 + )
176 + );
177 + }
178 + ?></li>
122 179 <!-- <li class="fs-tag"></li> -->
123 180 <li class="fs-title"><?php echo $addon->title ?></li>
124 181 <li class="fs-offer">
125 182 <span
@@ -135,9 +192,116 @@
135 192
136 193 echo implode(' - ', $descriptors) ?></span>
137 194 </li>
138 195 <li class="fs-description"><?php echo ! empty( $addon->info->short_description ) ? $addon->info->short_description : 'SHORT DESCRIPTION' ?></li>
139 - <li class="fs-cta"><a class="button"><?php fs_esc_html_echo_inline( 'View details', 'view-details', $slug ) ?></a></li>
196 + <?php
197 + $is_free_only_wp_org_compliant = ( ! $has_paid_plan && $addon->is_wp_org_compliant );
198 +
199 + $is_allowed_to_install = (
200 + $fs->is_allowed_to_install() ||
201 + $is_free_only_wp_org_compliant
202 + );
203 +
204 + $show_premium_activation_or_installation_action = true;
205 +
206 + if ( ! in_array( $addon->id, $account_addon_ids ) ) {
207 + $show_premium_activation_or_installation_action = false;
208 + } else if ( $is_addon_installed ) {
209 + /**
210 + * If any add-on's version (free or premium) is installed, check if the
211 + * premium version can be activated and show the relevant action. Otherwise,
212 + * show the relevant action for the free version.
213 + *
214 + * @author Leo Fajardo (@leorw)
215 + * @since 2.4.5
216 + */
217 + $fs_addon = $is_addon_activated ?
218 + $fs->get_addon_instance( $addon->id ) :
219 + null;
220 +
221 + $premium_plugin_basename = is_object( $fs_addon ) ?
222 + $fs_addon->premium_plugin_basename() :
223 + "{$addon->premium_slug}/{$addon->slug}.php";
224 +
225 + if (
226 + ( $is_addon_activated && $fs_addon->is_premium() ) ||
227 + file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $premium_plugin_basename ) )
228 + ) {
229 + $basename = $premium_plugin_basename;
230 + }
231 +
232 + $show_premium_activation_or_installation_action = (
233 + ( ! $is_addon_activated || ! $fs_addon->is_premium() ) &&
234 + /**
235 + * This check is needed for cases when an active add-on doesn't have an
236 + * associated Freemius instance.
237 + *
238 + * @author Leo Fajardo (@leorw)
239 + * @since 2.4.5
240 + */
241 + ( ! $is_plugin_active )
242 + );
243 + }
244 + ?>
245 + <?php if ( ! $show_premium_activation_or_installation_action ) : ?>
246 + <li class="fs-cta"><a class="button"><?php echo esc_html( $view_details_text ) ?></a></li>
247 + <?php else : ?>
248 + <?php
249 + $latest_download_local_url = $is_free_only_wp_org_compliant ?
250 + null :
251 + $fs->_get_latest_download_local_url( $addon->id );
252 + ?>
253 +
254 + <li class="fs-cta fs-dropdown">
255 + <div class="button-group">
256 + <?php if ( $is_allowed_to_install ) : ?>
257 + <?php
258 + if ( ! $is_addon_installed ) {
259 + echo sprintf(
260 + '<a class="button button-primary" href="%s">%s</a>',
261 + wp_nonce_url( self_admin_url( 'update.php?' . ( ( $has_paid_plan || ! $addon->is_wp_org_compliant ) ? 'fs_allow_updater_and_dialog=true&' : '' ) . 'action=install-plugin&plugin=' . $addon->slug ), 'install-plugin_' . $addon->slug ),
262 + fs_esc_html_inline( 'Install Now', 'install-now', $slug )
263 + );
264 + } else {
265 + echo sprintf(
266 + '<a class="button button-primary edit" href="%s" title="%s" target="_parent">%s</a>',
267 + wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . $basename, 'activate-plugin_' . $basename ),
268 + fs_esc_attr_inline( 'Activate this add-on', 'activate-this-addon', $addon->slug ),
269 + fs_text_inline( 'Activate', 'activate', $addon->slug )
270 + );
271 + }
272 + ?>
273 + <?php else : ?>
274 + <a target="_blank" class="button button-primary" href="<?php echo $latest_download_local_url ?>"><?php echo esc_html( $download_latest_text ) ?></a>
275 + <?php endif ?>
276 + <div class="button button-primary fs-dropdown-arrow-button"><span class="fs-dropdown-arrow"></span><ul class="fs-dropdown-list" style="display: none">
277 + <?php if ( $is_allowed_to_install && ! empty( $latest_download_local_url ) ) : ?>
278 + <li><a target="_blank" href="<?php echo $latest_download_local_url ?>"><?php echo esc_html( $download_latest_text ) ?></a></li>
279 + <?php endif ?>
280 + <li><?php
281 + echo sprintf(
282 + $view_details_link,
283 + /**
284 + * No additional class.
285 + *
286 + * @author Leo Fajardo (@leorw)
287 + * @since 2.2.4
288 + */
289 + '',
290 + /**
291 + * Set the view details link text to a non-empty string since it is an
292 + * item in the dropdown list and the text should be visible.
293 + *
294 + * @author Leo Fajardo (@leorw)
295 + * @since 2.2.4
296 + */
297 + esc_html( $view_details_text )
298 + );
299 + ?></li>
300 + </ul></div>
301 + </div>
302 + </li>
303 + <?php endif ?>
140 304 </ul>
141 305 </div>
142 306 </li>
143 307 <?php endforeach ?>
@@ -143,11 +307,13 @@
143 307 <?php endforeach ?>
144 308 <?php endif ?>
145 309 </ul>
146 310 </div>
311 +
312 + <?php $fs->do_action( 'addons/after_addons' ) ?>
147 313 </div>
148 314 <script type="text/javascript">
149 - (function ($) {
315 + (function( $, undef ) {
150 316 <?php if ( $open_addon ) : ?>
151 317
152 318 var interval = setInterval(function () {
153 319 // Open add-on information page.
@@ -170,18 +336,96 @@
170 336 }, 200);
171 337
172 338 <?php else : ?>
173 339
340 + $( '.fs-card.fs-addon' )
341 + .mouseover(function() {
342 + var $this = $( this );
174 343
175 - $('.fs-card.fs-addon')
176 - .mouseover(function () {
177 - $(this).find('.fs-cta .button').addClass('button-primary');
178 - }).mouseout(function () {
179 - $(this).find('.fs-cta .button').removeClass('button-primary');
180 - });
344 + $this.find( '.fs-cta .button' ).addClass( 'button-primary' );
181 345
346 + if ( 0 === $this.find( '.fs-dropdown-arrow-button.active' ).length ) {
347 + /**
348 + * When hovering over a card, close the dropdown on any other card.
349 + *
350 + * @author Leo Fajardo (@leorw)
351 + * @since 2.2.4
352 + */
353 + toggleDropdown();
354 + }
355 + }).mouseout(function( evt ) {
356 + var $relatedTarget = $( evt.relatedTarget );
357 +
358 + if ( 0 !== $relatedTarget.parents( '.fs-addon' ).length ) {
359 + return true;
360 + }
361 +
362 + var $this = $( this );
363 +
364 + /**
365 + * Set the color of the "View details" button to "secondary".
366 + *
367 + * @author Leo Fajardo (@leorw)
368 + * @since 2.2.4
369 + */
370 + $this.find( '.fs-cta .button' ).filter(function() {
371 + /**
372 + * Keep the "primary" color of the dropdown arrow button, "Install Now" button, and
373 + * "Download Latest" button.
374 +
375 + * @author Leo Fajardo (@leorw)
376 + * @since 2.2.4
377 + */
378 + return $( this ).parent().is( ':not(.button-group)' );
379 + }).removeClass('button-primary');
380 +
381 + toggleDropdown( $this.find( '.fs-dropdown' ), false );
382 + }).find( 'a.thickbox, .button:not(.fs-dropdown-arrow-button)' ).click(function() {
383 + toggleDropdown();
384 + });
385 +
182 386 <?php endif ?>
183 - })(jQuery);
387 +
388 + var $dropdowns = $( '.fs-dropdown' );
389 + if ( 0 !== $dropdowns.length ) {
390 + $dropdowns.find( '.fs-dropdown-arrow-button' ).click(function() {
391 + var $this = $( this ),
392 + $dropdown = $this.parents( '.fs-dropdown' );
393 +
394 + toggleDropdown( $dropdown, ! $dropdown.hasClass( 'active' ) );
395 + });
396 + }
397 +
398 + /**
399 + * Returns the default state of the dropdown arrow button and hides the dropdown list.
400 + *
401 + * @author Leo Fajardo (@leorw)
402 + * @since 2.2.4
403 + *
404 + * @param {(Object|undefined)} [$dropdown]
405 + * @param {(Boolean|undefined)} [state]
406 + */
407 + function toggleDropdown( $dropdown, state ) {
408 + if ( undef === $dropdown ) {
409 + var $activeDropdown = $dropdowns.find( '.active' );
410 + if ( 0 !== $activeDropdown.length ) {
411 + $dropdown = $activeDropdown;
412 + }
413 + }
414 +
415 + if ( undef === $dropdown ) {
416 + return;
417 + }
418 +
419 + if ( undef === state ) {
420 + state = false;
421 + }
422 +
423 + $dropdown.toggleClass( 'active', state );
424 + $dropdown.find( '.fs-dropdown-list' ).toggle( state );
425 + $dropdown.find( '.fs-dropdown-arrow-button' ).toggleClass( 'active', state );
426 + }
427 + })( jQuery );
184 428 </script>
185 429 <?php
186 430 if ( $has_tabs ) {
187 431 $fs->_add_tabs_after_content();