From a105c29d2440af6c08a121a1cf3f9e5c39182b2f Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Thu, 15 Oct 2020 06:22:35 -0400 Subject: [PATCH 01/17] WPCS; plugin url update; new functions to return and filter CSS for output. --- pmpro-advanced-levels-shortcode.php | 293 +++++++++++++++++++++++++--- 1 file changed, 266 insertions(+), 27 deletions(-) diff --git a/pmpro-advanced-levels-shortcode.php b/pmpro-advanced-levels-shortcode.php index 790785d..f6d21b3 100644 --- a/pmpro-advanced-levels-shortcode.php +++ b/pmpro-advanced-levels-shortcode.php @@ -1,11 +1,11 @@ id; + } $args = array( - 'post_type' => apply_filters('pmproal_level_landing_page_post_types', array('page', 'post')), + 'post_type' => apply_filters( 'pmproal_level_landing_page_post_types', array( 'page', 'post' ) ), 'meta_query' => array( array( 'key' => '_pmproal_landing_page_level', @@ -55,26 +58,262 @@ function pmproal_getLevelLandingPage($level_id) { ) ); - $posts = get_posts($args); + $posts = get_posts( $args ); - if(empty($posts)) + if ( empty( $posts ) ) { return false; - else + } else { return $posts[0]; + } } -/* -Function to add links to the plugin row meta -*/ -function pmpro_advanced_levels_plugin_row_meta($links, $file) { - if(strpos($file, 'pmpro-advanced-levels-shortcode.php') !== false) - { +/** + * Get the class for the wrapping levels output div. + * + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @return string + * + */ +function pmpro_advanced_levels_wrapper_class( $layout, $template ) { + + // The return variable + $r = ''; + + // Get the class name for the chosen template, if available. + if ( ! empty( $template ) ) { + $r .= ' pmpro_advanced_levels-' . $template; + } + + // Add the class for the chosen layout, if available. + if ( ! empty( $layout ) ) { + if ( $layout == 'table' ) { + $r .= ' pmpro_advanced_levels-table'; + if ( $template === 'gantry' || $template === 'bootstrap' ) { + $r .= ' table table-striped table-bordered'; + } + } + + $r .= ' pmpro_levels-' . $layout; + } + + /** + * Allow custom code to filter the levels output class. + * + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_wrapper_class', $r, $layout, $template ); + + return $r; +} + +/** + * Get the class for the individual level item output. + * + * @param int level_id The ID of the level displayed. + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @return string + * + */ +function pmpro_advanced_levels_level_class( $level_id, $layout, $template ) { + + // The return variable. + $r = 'pmpro_level'; + + /** + * Allow custom code to filter the level output class. + * + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_level_class', $r, $level_id, $layout, $template ); + + return $r; +} + +/** + * Get the class for the inner div for each level item output. + * + * @param int level_id The ID of the level displayed. + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @param object current_level The current user's level object if set. + * @param int highlight The ID of the level to highlight if set. + * @return string + * + */ +function pmpro_advanced_levels_level_inner_class( $level_id, $layout, $template, $current_level, $highlight ) { + + // The return variable + $r = ''; + + if ( ! in_array( $layout, array( 'table', 'compare_table' ) ) ) { + $r .= ' entry post'; + } + + if ( $level_id == $current_level ) { + $r .= ' pmpro_level-current'; + } + + if ( $level_id == $highlight ) { + $r .= ' pmpro_level-highlight'; + } + + /** + * Allow custom code to filter the level output class. + * + * @param int level_id The ID of the level displayed. + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @param int current_level The current user's level ID if set. + * @param int highlight The ID of the level to highlight if set. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_level_inner_class', $r, $level_id, $layout, $template, $current_level, $highlight ); + + return $r; +} + +/** + * Get the class for the inner div for each level item output. + * + * @param int level_id The ID of the level displayed. + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @param int current_level The current user's level ID if set. + * @return string + */ +function pmpro_advanced_levels_level_button_class( $level_id, $layout, $template, $current_level ) { + + // The return variable. + $r = 'pmpro_level_btn'; + + if ( in_array( $template, array( 'genesis', 'twentyfourteen', 'foundation' ) ) ) { + $r .= ' button'; + } elseif ( in_array( $template, array( 'gantry', 'bootstrap' ) ) ) { + $r .= ' btn btn-primary'; + } elseif ( $template === 'woothemes') { + $r .= ' woo-sc-button custom'; + } else { + $r .= ' pmpro_btn pmpro_btn-select'; + } + + // Show a disabled/greyed button that links to Account page. + if ( ! empty( $current_level ) && $level_id == $current_level->id ) { + // If it's a one-time-payment level, offer a link to renew. + if ( ! pmpro_isLevelRecurring( $current_level ) && ! empty( $current_user->membership_level->enddate ) ) { + $r .= ' pmpro_btn-renew'; + } else { + $r .= ' pmpro_btn-disabled'; + } + } + + /** + * Allow custom code to filter the level output class. + * + * @param int level_id The ID of the level displayed. + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @param int current_level The current user's level ID if set. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_level_button_class', $r, $level_id, $layout, $template, $current_level ); + + return $r; +} + +/** + * Get the button text for the checkout, renew, or account link for each level item output. + * + * @param int level_id The ID of the level displayed. + * @param object current_level The current user's level object if set. + * @param string checkout_button Text for checkout button passed in shortcode attributes. + * @param string renew_button Text for renew button passed in shortcode attributes. + * @param string account_button Text for account button passed in shortcode attributes. + * @return string + */ +function pmpro_advanced_levels_level_button_text( $level_id, $current_level, $checkout_button, $renew_button, $account_button ) { + + // The return variable. + $r = ''; + + if ( ! empty( $current_level ) && $level_id == $current_level->id ) { + // If it's a one-time-payment level, offer a link to renew. + if ( ! pmpro_isLevelRecurring( $current_level ) && ! empty( $current_user->membership_level->enddate ) ) { + $r = $renew_button; + } else { + $r = $account_button; + } + } else { + $r = $checkout_button; + } + + /** + * Allow custom code to filter the level button text. + * + * @param int level_id The ID of the level displayed. + * @param object current_level The current user's level object if set. + * @param string checkout_button Text for checkout button passed in shortcode attributes. + * @param string renew_button Text for renew button passed in shortcode attributes. + * @param string account_button Text for account button passed in shortcode attributes. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_level_button_text', $r, $level_id, $current_level, $checkout_button, $renew_button, $account_button ); + + return $r; +} + +/** + * Build the href for the checkout, renew, or account link for each level item output. + * + * @param int level_id The ID of the level displayed. + * @param object current_level The current user's level object if set. + * @return string + */ +function pmpro_advanced_levels_level_button_link( $pmproal_link_arguments, $level_id, $current_level ) { + + // The return variable. + $r = ''; + + if ( ! empty( $current_level ) && $level_id == $current_level->id ) { + // If it's a one-time-payment level, offer a link to renew. + if ( ! pmpro_isLevelRecurring( $current_level ) && ! empty( $current_user->membership_level->enddate ) ) { + $r = add_query_arg( $pmproal_link_arguments, pmpro_url( 'checkout', null, 'https' ) ); + } else { + $r = add_query_arg( $pmproal_link_arguments, pmpro_url( 'account', null, 'https' ) ); + } + } else { + $r = add_query_arg( $pmproal_link_arguments, pmpro_url( 'checkout', null, 'https' ) ); + } + + /** + * Allow custom code to filter the level href. + * + * @param int level_id The ID of the level displayed. + * @param object current_level The current user's level object if set. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_level_button_link', $r, $pmproal_link_arguments, $level_id, $current_level ); + + return $r; +} + +/** + * Function to add links to the plugin row meta + * + */ +function pmpro_advanced_levels_plugin_row_meta( $links, $file ) { + if ( strpos( $file, 'pmpro-advanced-levels-shortcode.php' ) !== false ) { $new_links = array( - '' . __( 'Docs', 'pmpro-advanced-levels-shortcode' ) . '', - '' . __( 'Support', 'pmpro-advanced-levels-shortcode' ) . '', + '' . __( 'Docs', 'pmpro-advanced-levels-shortcode' ) . '', + '' . __( 'Support', 'pmpro-advanced-levels-shortcode' ) . '', ); $links = array_merge($links, $new_links); } return $links; } -add_filter('plugin_row_meta', 'pmpro_advanced_levels_plugin_row_meta', 10, 2); +add_filter( 'plugin_row_meta', 'pmpro_advanced_levels_plugin_row_meta', 10, 2 ); From f0a07190899ab33c52a3c3d5fa38bc6ee706132b Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Thu, 15 Oct 2020 06:26:47 -0400 Subject: [PATCH 02/17] Start of the overhaul to how the HTML is generated for div-based and the basic table layout types. --- css/pmpro-advanced-levels.css | 160 ++++++++---- templates/levels-div.php | 473 ++++------------------------------ templates/levels-table.php | 145 ++++------- 3 files changed, 203 insertions(+), 575 deletions(-) diff --git a/css/pmpro-advanced-levels.css b/css/pmpro-advanced-levels.css index aff3919..c8af64c 100755 --- a/css/pmpro-advanced-levels.css +++ b/css/pmpro-advanced-levels.css @@ -60,66 +60,116 @@ table.pmpro_advanced_levels-woothemes tbody td {vertical-align: middle; } .pmpro_advanced_levels-compare_table_responsive {display: block; } } -.pmpro_advanced_levels-div .row { - width: 100%; - margin-left: auto; - margin-right: auto; - margin-top: 0; - margin-bottom: 0; - max-width: 73.125em; } - .pmpro_advanced_levels-div .row:before, .pmpro_advanced_levels-div .row:after { - content: " "; - display: table; } - .pmpro_advanced_levels-div .row:after { - clear: both; } - .pmpro_advanced_levels-div .column, - .pmpro_advanced_levels-div .columns { - position: relative; - float: left; } - -.pmpro_advanced_levels-div [class*="column"] + [class*="column"]:last-child { - float: right; } - -.pmpro_advanced_levels-div [class*="column"] + [class*="column"].end { - float: left; } - -.pmpro_advanced_levels-div .small-12 { - width: 100%; } - -@media only screen and (min-width: 40.063em) { - .pmpro_advanced_levels-div .medium-1 { - width: 8.33333%; } - - .pmpro_advanced_levels-div .medium-2 { - width: 16.66667%; } - - .pmpro_advanced_levels-div .medium-3 { - width: 25%; } - - .pmpro_advanced_levels-div .medium-4 { - width: 33.33333%; } +/* Div-based Levels Page Layouts */ +.pmpro_level .level-name { + grid-area: level-name; +} +.pmpro_level .level-description { + grid-area: level-description; +} +.pmpro_level .pmpro_level-price { + grid-area: level-price; +} +.pmpro_level .level-button { + grid-area: level-button; +} +.pmpro_level .pmpro_level-expiration { + grid-area: level-expiration; +} - .pmpro_advanced_levels-div .medium-5 { - width: 41.66667%; } +/* Column-based Levels Page Layouts */ +.pmpro_levels-2col, +.pmpro_levels-3col, +.pmpro_levels-4col { + display: grid; + grid-column-gap: 2em; + grid-row-gap: 2em; +} +.pmpro_levels-2col p, +.pmpro_levels-3col p, +.pmpro_levels-4col p { + margin: 0; +} - .pmpro_advanced_levels-div .medium-6 { - width: 50%; } +/* One Column (Div) Levels Page Layout */ +.pmpro_levels-div .pmpro_level_btn { + float: right; +} - .pmpro_advanced_levels-div .medium-7 { - width: 58.33333%; } +/* Two Column Levels Page Layout */ +.pmpro_levels-2col { + grid-template-columns: 1fr 1fr; +} +.pmpro_levels-2col .pmpro_level_btn { + float: right; +} - .pmpro_advanced_levels-div .medium-8 { - width: 66.66667%; } +/* Three Column Levels Page Layout */ +.pmpro_levels-3col { + grid-template-columns: 1fr 1fr 1fr; +} +.pmpro_levels-3col .pmpro_level { + text-align: center; +} +.pmpro_levels-3col .pmpro_level .post { + display: grid; + grid-gap: 1em; + grid-template-columns: 1fr; + grid-template-areas: + "level-name" + "level-price" + "level-button" + "level-description" + "level-expiration"; +} +.pmpro_levels-3col .pmpro_btn { + display: block; +} - .pmpro_advanced_levels-div .medium-9 { - width: 75%; } +/* Four Column Levels Page Layout */ +.pmpro_levels-4col { + grid-template-columns: 1fr 1fr 1fr 1fr; +} +.pmpro_levels-4col .pmpro_level { + text-align: center; +} +.pmpro_levels-4col .pmpro_level .post { + display: grid; + grid-gap: 1em; + grid-template-columns: 1fr; + grid-template-areas: + "level-name" + "level-price" + "level-button" + "level-description" + "level-expiration"; +} +.pmpro_levels-4col .pmpro_btn { + display: block; +} - .pmpro_advanced_levels-div .medium-10 { - width: 83.33333%; } +@media only screen and (min-width: 960px) and (max-width: 1160px) { + .pmpro_levels-3col { + grid-template-columns: 1fr 1fr 1fr; + } + .pmpro_levels-4col { + grid-template-columns: 1fr 1fr 1fr 1fr; + } +} - .pmpro_advanced_levels-div .medium-11 { - width: 91.66667%; } +/* Tablet Portrait */ +@media only screen and (min-width: 768px) and (max-width: 959px) { + .pmpro_levels-3col, + .pmpro_levels-4col { + grid-template-columns: 1fr 1fr; + } +} - .pmpro_advanced_levels-div .medium-12 { - width: 100%; } -} \ No newline at end of file +/* Mobile */ +@media only screen and (max-width: 767px) { + .pmpro_levels-2col, + .pmpro_levels-3col, + .pmpro_levels-4col { + grid-template-columns: 1fr; + } +} diff --git a/templates/levels-div.php b/templates/levels-div.php index 78fe1fc..1f4ce86 100644 --- a/templates/levels-div.php +++ b/templates/levels-div.php @@ -1,446 +1,67 @@ -
membership_level->ID ) ) { + $current_level = $current_user->membership_level; + } else { + $current_level = false; } -?>"> -id; - $count++; - if(isset($current_user->membership_level->ID)) - $current_level = ($current_user->membership_level->ID == $level->id); - else - $current_level = false; + + foreach( $pmpro_levels_filtered as $level ) { + $pmproal_link_arguments['level'] = $level->id; ?> -
1) { echo '12'; } } - if($count == 1) { echo ' first'; } - } - elseif($template === "bootstrap") { - if($layout == '2col') { echo 'col-md-6'; } - elseif($layout == '3col') { echo 'col-md-4'; } - elseif($layout == '4col') { echo 'col-md-3'; } - else { if(count($pmpro_levels_filtered) > 1) { echo 'col-md-12'; } } - } - elseif($template === "gantry") { - if($layout == '2col') { echo 'span6'; } - elseif($layout == '3col') { echo 'span4'; } - elseif($layout == '4col') { echo 'span3'; } - else { if(count($pmpro_levels_filtered) > 1) { echo 'span12'; } } - } - elseif($template === "twentyfourteen") { - if($layout == '2col' || $layout == '3col' ||$layout == '4col') { echo 'gallery-item'; } - } - elseif($template === "woothemes") { - if($layout == '2col') { echo 'twocol-one'; } - elseif($layout == '3col') { echo 'threecol-one'; } - elseif($layout == '4col') { echo 'fourcol-one'; } - else { if(count($pmpro_levels_filtered) > 1) { echo 'full'; } } - if($layout == '2col' && $count % 2 == 0) { echo ' last'; } - elseif($layout == '3col' && $count % 3 == 0) { echo ' last'; } - elseif($layout == '4col' && $count % 4 == 0) { echo ' last'; } - } - else - { - ?> - small-12 medium- 1) { echo '12'; } } - ?> columns - "> -
id) { echo "pmpro_level-highlight "; } if($template === "foundation" && ($layout === "2col" || $layout === "div" || empty($layout))) { echo " panel"; } if($template === "gantry") { echo " well"; } if($template === "bootstrap") { echo " panel panel-default"; } ?>"> - id, $layout); ?> - -
    -
  • name?>
  • - -
  • - - - - - -
  • - - -
  • - description; ?> -
  • - - '; - $level_expiration = pmpro_getLevelExpiration($level); - if(empty($level_expiration)) - _e('Membership Never Expires.', 'pmpro-advanced-levels-shortcode'); - else - echo $level_expiration; - echo ''; - } - ?> -
  • membership_level->ID)) - { - ?> - " href=""> - - " href=""> - membership_level) && !empty($current_user->membership_level->enddate)) - { - ?> - " href=""> - - " href=""> -
  • -
- - class="entry-header">>name?> - -
"> - - - class="entry-content"> - description); ?> +
+ +
+ + id, $layout ); ?> + +

name; ?>

+ + +
+ description ); ?>
- - class="entry-footer"> '; } ?> -
- id, $layout, $template, $current_level ); ?>" href="id, $current_level ); ?>">id, $current_level, $checkout_button, $renew_button, $account_button ); ?> + + + + + + - class="entry-content"> - -

"> - -

- - -

membership_level->ID)) - { - ?> - " href=""> - - " href=""> - membership_level) && !empty($current_user->membership_level->enddate)) - { - ?> - " href=""> - - " href=""> -

+
+ - "; - echo wpautop($level->description); - } - ?> -
+ + '; - $level_expiration = pmpro_getLevelExpiration($level); - if(empty($level_expiration)) - _e('Membership Never Expires.', 'pmpro-advanced-levels-shortcode'); - else - echo $level_expiration; - echo ''; - } - ?> + $level_expiration = pmpro_getLevelExpiration( $level ); - - -
+ if ( empty( $level_expiration ) ) { + _e( 'Membership Never Expires.', 'pmpro-advanced-levels-shortcode' ); + } else { + echo $level_expiration; + } + ?> + -
- id, $layout); ?> + + id, $layout ); ?> +
- \ No newline at end of file + diff --git a/templates/levels-table.php b/templates/levels-table.php index 11ea887..1e8804f 100644 --- a/templates/levels-table.php +++ b/templates/levels-table.php @@ -5,119 +5,76 @@ global $pmproal_link_arguments; ?> -"> +
- - - - + + + + - - + + - + id; - - if(isset($current_user->membership_level->ID)) - $current_level = ($current_user->membership_level->ID == $level->id); - else + foreach( $pmpro_levels_filtered as $level ) { + $pmproal_link_arguments['level'] = $level->id; + if ( isset( $current_user->membership_level->ID ) ) { + $current_level = $current_user->membership_level; + } else { $current_level = false; + } ?> - - id, $template); ?> + + + id, $template ); ?> + - - + + + + - - - - + + - id, $template); ?> + + id, $template ); ?> + Date: Thu, 15 Oct 2020 07:05:00 -0400 Subject: [PATCH 03/17] Cleaning up a few lines where merge code was lost. Textdomain fix. --- pmpro-advanced-levels-shortcode.php | 4 ++-- templates/levels-compare_table.php | 10 ++++------ templates/levels-div.php | 6 +----- templates/levels-table.php | 6 +----- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/pmpro-advanced-levels-shortcode.php b/pmpro-advanced-levels-shortcode.php index f6d21b3..f45d1ae 100644 --- a/pmpro-advanced-levels-shortcode.php +++ b/pmpro-advanced-levels-shortcode.php @@ -204,8 +204,8 @@ function pmpro_advanced_levels_level_button_class( $level_id, $layout, $template // Show a disabled/greyed button that links to Account page. if ( ! empty( $current_level ) && $level_id == $current_level->id ) { - // If it's a one-time-payment level, offer a link to renew. - if ( ! pmpro_isLevelRecurring( $current_level ) && ! empty( $current_user->membership_level->enddate ) ) { + // If it's a one-time-payment level or recurring level that's expiring soon, offer a link to renew. + if ( pmpro_isLevelExpiringSoon( $current_user->membership_level ) && $current_user->membership_level->allow_signups ) { $r .= ' pmpro_btn-renew'; } else { $r .= ' pmpro_btn-disabled'; diff --git a/templates/levels-compare_table.php b/templates/levels-compare_table.php index b50dcdd..e6fcdc6 100644 --- a/templates/levels-compare_table.php +++ b/templates/levels-compare_table.php @@ -7,7 +7,7 @@
 
-

name?>

- description); } ?> +

name; ?>

+ +
+ description ); ?> +
+
+ + + + + - - - - membership_level->ID)) { ?> - " href=""> - - " href=""> - - - membership_level) && !empty($current_user->membership_level->enddate)) - { - ?> - " href=""> - - " href=""> - - - + id, $current_level, $checkout_button, $renew_button, $account_button ); ?>
pmpro_advanced_levels-compare_table"> - + " href="">membership_level) && $current_user->membership_level->allow_signups ) - { - ?> + // If it's a one-time-payment level or recurring level that's expiring soon, offer a link to renew + if ( pmpro_isLevelExpiringSoon( $current_user->membership_level) && $current_user->membership_level->allow_signups ) { ?> diff --git a/templates/levels-div.php b/templates/levels-div.php index 1f4ce86..d9d32c3 100644 --- a/templates/levels-div.php +++ b/templates/levels-div.php @@ -6,11 +6,7 @@ ?>
membership_level->ID ) ) { - $current_level = $current_user->membership_level; - } else { - $current_level = false; - } + $current_level = pmpro_hasMembershipLevel( $level->id ); foreach( $pmpro_levels_filtered as $level ) { $pmproal_link_arguments['level'] = $level->id; diff --git a/templates/levels-table.php b/templates/levels-table.php index 60fd575..2ccd474 100644 --- a/templates/levels-table.php +++ b/templates/levels-table.php @@ -24,11 +24,7 @@ id; - if ( isset( $current_user->membership_level->ID ) ) { - $current_level = $current_user->membership_level; - } else { - $current_level = false; - } + $current_level = pmpro_hasMembershipLevel( $level->id ); ?>
From c8fcf3859d30cfc18866b144207ec667840c1f15 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Thu, 15 Oct 2020 07:10:44 -0400 Subject: [PATCH 04/17] Convert to UNIX line endings --- css/pmpro-advanced-levels.css | 349 +++++----- pmpro-advanced-levels-shortcode.php | 638 +++++++++---------- readme.txt | 208 +++--- templates/levels-compare_table.php | 956 ++++++++++++++-------------- templates/levels-div.php | 126 ++-- templates/levels-table.php | 158 ++--- templates/levels.php | 394 ++++++------ 7 files changed, 1414 insertions(+), 1415 deletions(-) diff --git a/css/pmpro-advanced-levels.css b/css/pmpro-advanced-levels.css index c8af64c..0e19b39 100755 --- a/css/pmpro-advanced-levels.css +++ b/css/pmpro-advanced-levels.css @@ -1,175 +1,174 @@ -@charset "UTF-8"; -/* CSS Document */ -.pmpro_advanced_levels-genesis .pmpro_level.one-third, .pmpro_advanced_levels-genesis .pmpro_level.one-fourth, .pmpro_advanced_levels-gantry .pmpro_level.span4, .pmpro_advanced_levels-gantry .pmpro_level.span3, .pmpro_advanced_levels-woothemes .pmpro_level.threecol-one, .pmpro_advanced_levels-woothemes .pmpro_level.fourcol-one, .pmpro_advanced_levels-div .text-center, .pmpro_advanced_levels-compare_table th, .pmpro_advanced_levels-compare_table td {text-align: center; } -table.pmpro_advanced_levels-genesis .button, .pmpro_advanced_levels-genesis .pmpro_level.one-third .button, .pmpro_advanced_levels-genesis .pmpro_level.one-fourth .button, table.pmpro_advanced_levels-foundation .button, .pmpro_advanced_levels-foundation .pmpro_level.medium-4 .button, .pmpro_advanced_levels-foundation .pmpro_level.medium-3 .button, table.pmpro_advanced_levels-gantry .btn, table.pmpro_advanced_levels-woothemes .woo-sc-button, .pmpro_advanced_levels-woothemes .pmpro_level.threecol-one .woo-sc-button, .pmpro_advanced_levels-woothemes .pmpro_level.fourcol-one .woo-sc-button, table.pmpro_advanced_levels-twentyfourteen .button, .pmpro_advanced_levels-table .pmpro_btn, .pmpro_advanced_levels-div .text-center .pmpro_btn, table.pmpro_advanced_levels-bootstrap .btn, .pmpro_advanced_levels-compare_table .pmpro_btn, .pmpro_advanced_levels-compare_table_responsive .pmpro_btn, .pmpro_advanced_levels-compare_table_responsive .button {display: block; text-align: center; word-break: normal; } -#pmpro_levels .pmpro_btn:hover {-webkit-box-shadow: none; box-shadow: none; } -.pmpro_advanced_levels-compare_table {border: none; } -#pmpro_levels.pmpro_advanced_levels-table h2 {margin: 0; } -.pmpro_advanced_levels-compare_table th, .pmpro_advanced_levels-compare_table td {border-color: #d1d1d1; border-width: 0 1px 1px 0; padding: .75em 1em; vertical-align: middle; } -.pmpro_advanced_levels-compare_table thead th, .pmpro_advanced_levels-compare_table tfoot td {border-width: 0 1px 0 0; } -.pmpro_advanced_levels-compare_table thead tr {border: none; } -.pmpro_advanced_levels-compare_table tr th:last-child, .pmpro_advanced_levels-compare_table tr td:last-child {border-right: none; } -.pmpro_advanced_levels-compare_table thead tr th:nth-child(even), .pmpro_advanced_levels-compare_table tbody tr td:nth-child(even) {background: rgba(0,0,0,0.02); } -.pmpro_advanced_levels-compare_table thead tr th:first-child, .pmpro_advanced_levels-compare_table tfoot tr td:first-child {background: none; text-indent: -9999em; width: 20%; } -.pmpro_advanced_levels-compare_table thead tr:last-child th, .pmpro_advanced_levels-compare_table tbody tr:last-child td {border-bottom: .5rem solid #CCC; } -.pmpro_advanced_levels-compare_table tbody tr:nth-child(even) td {background: rgba(0,0,0,0.05); } -.pmpro_advanced_levels-compare_table tbody tr td:first-child {text-align: right; } -.pmpro_advanced_levels-compare_table tfoot tr {border: none; } -.pmpro_advanced_levels-compare_table tfoot td {padding: .75em 1em; vertical-align: middle; } -.pmpro_advanced_levels-compare_table thead th h2 {margin: 0; padding: .5em 0 0 0; } -.pmpro_advanced_levels-compare_table .pmpro_level-price {font-size: 1.6rem; padding-bottom: 0; padding-top: 0; } -.pmpro_advanced_levels-compare_table .pmpro_level-expiration {font-weight: normal; } -.pmpro_advanced_levels-compare_table .pmpro_level-compare-true, .pmpro_advanced_levels-compare_table_responsive .pmpro_level-compare-true {font-size: 2rem; line-height: 2rem; } -.pmpro_advanced_levels-compare_table .pmpro_level-compare-true:after, .pmpro_advanced_levels-compare_table_responsive .pmpro_level-compare-true:after {content: "\2713"; } -.pmpro_advanced_levels-compare_table .pmpro_level-compare-false, .pmpro_advanced_levels-compare_table_responsive .pmpro_level-compare-false {color: rgba(0,0,0,0.2); } -.pmpro_advanced_levels-compare_table .pmpro_level-compare-false:after, .pmpro_advanced_levels-compare_table_responsive .pmpro_level-compare-false:after {content: "\002D"; } - -/* Styles for Bootstrap Template */ -table.pmpro_advanced_levels-bootstrap h2 {margin-top: 0; } -.pmpro_advanced_levels-bootstrap .panel-heading h2 {margin: 0; padding: 0; } - -/* Styles for Genesis Template */ -table.pmpro_advanced_levels-genesis thead th, table.pmpro_advanced_levels-genesis tbody td {padding-right: 10px; padding-left: 10px; } - -/* Styles for Gantry Template */ -table.pmpro_advanced_levels-gantry h2 {border-bottom: none; box-shadow: none; padding-bottom: 0; } - -/* Styles for WooThemes Template */ -table.pmpro_advanced_levels-woothemes tbody td {vertical-align: middle; } - -/* Styles for Foundation Template */ -.pmpro_advanced_levels-foundation .panel .button {margin-bottom: 0; } -.pmpro_advanced_levels-foundation .panel h5.subheader {color: #6f6f6f; } -.pmpro_advanced_levels-foundation .pricing-table .price {font-size: 1rem; } -.pmpro_advanced_levels-foundation .pricing-table .price span {display: block; font-size: 2rem; } - -/* Styles for TwentyFourteen Template */ -.pmpro_advanced_levels-twentyfourteen .button, .pmpro_advanced_levels-twentyfourteen .button:hover {color: #FFF; } - -/* Styles for No Template */ -#pmpro_levels.pmpro_advanced_levels-div .post {padding: 1em; } -#pmpro_levels.pmpro_advanced_levels-div h2 {margin: 0 0 .5em 0; } -#pmpro_levels.pmpro_advanced_levels-div .entry-header {margin: 0; padding: 0; } -#pmpro_levels.pmpro_advanced_levels-div .entry-content {padding: 0; } -#pmpro_levels.pmpro_advanced_levels-div .entry-footer {background: none; margin: 0; padding: 1em 0; } -#pmpro_levels.pmpro_advanced_levels-div .entry-footer p {margin: .5em 0; padding: 0; } -.pmpro_advanced_levels-compare_table_responsive {display: none; text-align: center; } - -@media only screen and (max-width: 767px) { - .pmpro_advanced_levels-compare_table {display: none; } - .pmpro_advanced_levels-compare_table_responsive {display: block; } -} - -/* Div-based Levels Page Layouts */ -.pmpro_level .level-name { - grid-area: level-name; -} -.pmpro_level .level-description { - grid-area: level-description; -} -.pmpro_level .pmpro_level-price { - grid-area: level-price; -} -.pmpro_level .level-button { - grid-area: level-button; -} -.pmpro_level .pmpro_level-expiration { - grid-area: level-expiration; -} - -/* Column-based Levels Page Layouts */ -.pmpro_levels-2col, -.pmpro_levels-3col, -.pmpro_levels-4col { - display: grid; - grid-column-gap: 2em; - grid-row-gap: 2em; -} -.pmpro_levels-2col p, -.pmpro_levels-3col p, -.pmpro_levels-4col p { - margin: 0; -} - -/* One Column (Div) Levels Page Layout */ -.pmpro_levels-div .pmpro_level_btn { - float: right; -} - -/* Two Column Levels Page Layout */ -.pmpro_levels-2col { - grid-template-columns: 1fr 1fr; -} -.pmpro_levels-2col .pmpro_level_btn { - float: right; -} - -/* Three Column Levels Page Layout */ -.pmpro_levels-3col { - grid-template-columns: 1fr 1fr 1fr; -} -.pmpro_levels-3col .pmpro_level { - text-align: center; -} -.pmpro_levels-3col .pmpro_level .post { - display: grid; - grid-gap: 1em; - grid-template-columns: 1fr; - grid-template-areas: - "level-name" - "level-price" - "level-button" - "level-description" - "level-expiration"; -} -.pmpro_levels-3col .pmpro_btn { - display: block; -} - -/* Four Column Levels Page Layout */ -.pmpro_levels-4col { - grid-template-columns: 1fr 1fr 1fr 1fr; -} -.pmpro_levels-4col .pmpro_level { - text-align: center; -} -.pmpro_levels-4col .pmpro_level .post { - display: grid; - grid-gap: 1em; - grid-template-columns: 1fr; - grid-template-areas: - "level-name" - "level-price" - "level-button" - "level-description" - "level-expiration"; -} -.pmpro_levels-4col .pmpro_btn { - display: block; -} - -@media only screen and (min-width: 960px) and (max-width: 1160px) { - .pmpro_levels-3col { - grid-template-columns: 1fr 1fr 1fr; - } - .pmpro_levels-4col { - grid-template-columns: 1fr 1fr 1fr 1fr; - } -} - -/* Tablet Portrait */ -@media only screen and (min-width: 768px) and (max-width: 959px) { - .pmpro_levels-3col, - .pmpro_levels-4col { - grid-template-columns: 1fr 1fr; - } -} - -/* Mobile */ -@media only screen and (max-width: 767px) { - .pmpro_levels-2col, - .pmpro_levels-3col, - .pmpro_levels-4col { - grid-template-columns: 1fr; - } -} +/* CSS Document */ +.pmpro_advanced_levels-genesis .pmpro_level.one-third, .pmpro_advanced_levels-genesis .pmpro_level.one-fourth, .pmpro_advanced_levels-gantry .pmpro_level.span4, .pmpro_advanced_levels-gantry .pmpro_level.span3, .pmpro_advanced_levels-woothemes .pmpro_level.threecol-one, .pmpro_advanced_levels-woothemes .pmpro_level.fourcol-one, .pmpro_advanced_levels-div .text-center, .pmpro_advanced_levels-compare_table th, .pmpro_advanced_levels-compare_table td {text-align: center; } +table.pmpro_advanced_levels-genesis .button, .pmpro_advanced_levels-genesis .pmpro_level.one-third .button, .pmpro_advanced_levels-genesis .pmpro_level.one-fourth .button, table.pmpro_advanced_levels-foundation .button, .pmpro_advanced_levels-foundation .pmpro_level.medium-4 .button, .pmpro_advanced_levels-foundation .pmpro_level.medium-3 .button, table.pmpro_advanced_levels-gantry .btn, table.pmpro_advanced_levels-woothemes .woo-sc-button, .pmpro_advanced_levels-woothemes .pmpro_level.threecol-one .woo-sc-button, .pmpro_advanced_levels-woothemes .pmpro_level.fourcol-one .woo-sc-button, table.pmpro_advanced_levels-twentyfourteen .button, .pmpro_advanced_levels-table .pmpro_btn, .pmpro_advanced_levels-div .text-center .pmpro_btn, table.pmpro_advanced_levels-bootstrap .btn, .pmpro_advanced_levels-compare_table .pmpro_btn, .pmpro_advanced_levels-compare_table_responsive .pmpro_btn, .pmpro_advanced_levels-compare_table_responsive .button {display: block; text-align: center; word-break: normal; } +#pmpro_levels .pmpro_btn:hover {-webkit-box-shadow: none; box-shadow: none; } +.pmpro_advanced_levels-compare_table {border: none; } +#pmpro_levels.pmpro_advanced_levels-table h2 {margin: 0; } +.pmpro_advanced_levels-compare_table th, .pmpro_advanced_levels-compare_table td {border-color: #d1d1d1; border-width: 0 1px 1px 0; padding: .75em 1em; vertical-align: middle; } +.pmpro_advanced_levels-compare_table thead th, .pmpro_advanced_levels-compare_table tfoot td {border-width: 0 1px 0 0; } +.pmpro_advanced_levels-compare_table thead tr {border: none; } +.pmpro_advanced_levels-compare_table tr th:last-child, .pmpro_advanced_levels-compare_table tr td:last-child {border-right: none; } +.pmpro_advanced_levels-compare_table thead tr th:nth-child(even), .pmpro_advanced_levels-compare_table tbody tr td:nth-child(even) {background: rgba(0,0,0,0.02); } +.pmpro_advanced_levels-compare_table thead tr th:first-child, .pmpro_advanced_levels-compare_table tfoot tr td:first-child {background: none; text-indent: -9999em; width: 20%; } +.pmpro_advanced_levels-compare_table thead tr:last-child th, .pmpro_advanced_levels-compare_table tbody tr:last-child td {border-bottom: .5rem solid #CCC; } +.pmpro_advanced_levels-compare_table tbody tr:nth-child(even) td {background: rgba(0,0,0,0.05); } +.pmpro_advanced_levels-compare_table tbody tr td:first-child {text-align: right; } +.pmpro_advanced_levels-compare_table tfoot tr {border: none; } +.pmpro_advanced_levels-compare_table tfoot td {padding: .75em 1em; vertical-align: middle; } +.pmpro_advanced_levels-compare_table thead th h2 {margin: 0; padding: .5em 0 0 0; } +.pmpro_advanced_levels-compare_table .pmpro_level-price {font-size: 1.6rem; padding-bottom: 0; padding-top: 0; } +.pmpro_advanced_levels-compare_table .pmpro_level-expiration {font-weight: normal; } +.pmpro_advanced_levels-compare_table .pmpro_level-compare-true, .pmpro_advanced_levels-compare_table_responsive .pmpro_level-compare-true {font-size: 2rem; line-height: 2rem; } +.pmpro_advanced_levels-compare_table .pmpro_level-compare-true:after, .pmpro_advanced_levels-compare_table_responsive .pmpro_level-compare-true:after {content: "\2713"; } +.pmpro_advanced_levels-compare_table .pmpro_level-compare-false, .pmpro_advanced_levels-compare_table_responsive .pmpro_level-compare-false {color: rgba(0,0,0,0.2); } +.pmpro_advanced_levels-compare_table .pmpro_level-compare-false:after, .pmpro_advanced_levels-compare_table_responsive .pmpro_level-compare-false:after {content: "\002D"; } + +/* Styles for Bootstrap Template */ +table.pmpro_advanced_levels-bootstrap h2 {margin-top: 0; } +.pmpro_advanced_levels-bootstrap .panel-heading h2 {margin: 0; padding: 0; } + +/* Styles for Genesis Template */ +table.pmpro_advanced_levels-genesis thead th, table.pmpro_advanced_levels-genesis tbody td {padding-right: 10px; padding-left: 10px; } + +/* Styles for Gantry Template */ +table.pmpro_advanced_levels-gantry h2 {border-bottom: none; box-shadow: none; padding-bottom: 0; } + +/* Styles for WooThemes Template */ +table.pmpro_advanced_levels-woothemes tbody td {vertical-align: middle; } + +/* Styles for Foundation Template */ +.pmpro_advanced_levels-foundation .panel .button {margin-bottom: 0; } +.pmpro_advanced_levels-foundation .panel h5.subheader {color: #6f6f6f; } +.pmpro_advanced_levels-foundation .pricing-table .price {font-size: 1rem; } +.pmpro_advanced_levels-foundation .pricing-table .price span {display: block; font-size: 2rem; } + +/* Styles for TwentyFourteen Template */ +.pmpro_advanced_levels-twentyfourteen .button, .pmpro_advanced_levels-twentyfourteen .button:hover {color: #FFF; } + +/* Styles for No Template */ +#pmpro_levels.pmpro_advanced_levels-div .post {padding: 1em; } +#pmpro_levels.pmpro_advanced_levels-div h2 {margin: 0 0 .5em 0; } +#pmpro_levels.pmpro_advanced_levels-div .entry-header {margin: 0; padding: 0; } +#pmpro_levels.pmpro_advanced_levels-div .entry-content {padding: 0; } +#pmpro_levels.pmpro_advanced_levels-div .entry-footer {background: none; margin: 0; padding: 1em 0; } +#pmpro_levels.pmpro_advanced_levels-div .entry-footer p {margin: .5em 0; padding: 0; } +.pmpro_advanced_levels-compare_table_responsive {display: none; text-align: center; } + +@media only screen and (max-width: 767px) { + .pmpro_advanced_levels-compare_table {display: none; } + .pmpro_advanced_levels-compare_table_responsive {display: block; } +} + +/* Div-based Levels Page Layouts */ +.pmpro_level .level-name { + grid-area: level-name; +} +.pmpro_level .level-description { + grid-area: level-description; +} +.pmpro_level .pmpro_level-price { + grid-area: level-price; +} +.pmpro_level .level-button { + grid-area: level-button; +} +.pmpro_level .pmpro_level-expiration { + grid-area: level-expiration; +} + +/* Column-based Levels Page Layouts */ +.pmpro_levels-2col, +.pmpro_levels-3col, +.pmpro_levels-4col { + display: grid; + grid-column-gap: 2em; + grid-row-gap: 2em; +} +.pmpro_levels-2col p, +.pmpro_levels-3col p, +.pmpro_levels-4col p { + margin: 0; +} + +/* One Column (Div) Levels Page Layout */ +.pmpro_levels-div .pmpro_level_btn { + float: right; +} + +/* Two Column Levels Page Layout */ +.pmpro_levels-2col { + grid-template-columns: 1fr 1fr; +} +.pmpro_levels-2col .pmpro_level_btn { + float: right; +} + +/* Three Column Levels Page Layout */ +.pmpro_levels-3col { + grid-template-columns: 1fr 1fr 1fr; +} +.pmpro_levels-3col .pmpro_level { + text-align: center; +} +.pmpro_levels-3col .pmpro_level .post { + display: grid; + grid-gap: 1em; + grid-template-columns: 1fr; + grid-template-areas: + "level-name" + "level-price" + "level-button" + "level-description" + "level-expiration"; +} +.pmpro_levels-3col .pmpro_btn { + display: block; +} + +/* Four Column Levels Page Layout */ +.pmpro_levels-4col { + grid-template-columns: 1fr 1fr 1fr 1fr; +} +.pmpro_levels-4col .pmpro_level { + text-align: center; +} +.pmpro_levels-4col .pmpro_level .post { + display: grid; + grid-gap: 1em; + grid-template-columns: 1fr; + grid-template-areas: + "level-name" + "level-price" + "level-button" + "level-description" + "level-expiration"; +} +.pmpro_levels-4col .pmpro_btn { + display: block; +} + +@media only screen and (min-width: 960px) and (max-width: 1160px) { + .pmpro_levels-3col { + grid-template-columns: 1fr 1fr 1fr; + } + .pmpro_levels-4col { + grid-template-columns: 1fr 1fr 1fr 1fr; + } +} + +/* Tablet Portrait */ +@media only screen and (min-width: 768px) and (max-width: 959px) { + .pmpro_levels-3col, + .pmpro_levels-4col { + grid-template-columns: 1fr 1fr; + } +} + +/* Mobile */ +@media only screen and (max-width: 767px) { + .pmpro_levels-2col, + .pmpro_levels-3col, + .pmpro_levels-4col { + grid-template-columns: 1fr; + } +} diff --git a/pmpro-advanced-levels-shortcode.php b/pmpro-advanced-levels-shortcode.php index f45d1ae..3b627b2 100644 --- a/pmpro-advanced-levels-shortcode.php +++ b/pmpro-advanced-levels-shortcode.php @@ -1,319 +1,319 @@ -id; - } - - $args = array( - 'post_type' => apply_filters( 'pmproal_level_landing_page_post_types', array( 'page', 'post' ) ), - 'meta_query' => array( - array( - 'key' => '_pmproal_landing_page_level', - 'value' => $level_id, - ) - ) - ); - - $posts = get_posts( $args ); - - if ( empty( $posts ) ) { - return false; - } else { - return $posts[0]; - } -} - -/** - * Get the class for the wrapping levels output div. - * - * @param string layout Optional layout passed in shortcode attributes. - * @param string template Optional template passed in shortcode attributes. - * @return string - * - */ -function pmpro_advanced_levels_wrapper_class( $layout, $template ) { - - // The return variable - $r = ''; - - // Get the class name for the chosen template, if available. - if ( ! empty( $template ) ) { - $r .= ' pmpro_advanced_levels-' . $template; - } - - // Add the class for the chosen layout, if available. - if ( ! empty( $layout ) ) { - if ( $layout == 'table' ) { - $r .= ' pmpro_advanced_levels-table'; - if ( $template === 'gantry' || $template === 'bootstrap' ) { - $r .= ' table table-striped table-bordered'; - } - } - - $r .= ' pmpro_levels-' . $layout; - } - - /** - * Allow custom code to filter the levels output class. - * - * @param string layout Optional layout passed in shortcode attributes. - * @param string template Optional template passed in shortcode attributes. - * - */ - $r = apply_filters( 'pmpro_advanced_levels_wrapper_class', $r, $layout, $template ); - - return $r; -} - -/** - * Get the class for the individual level item output. - * - * @param int level_id The ID of the level displayed. - * @param string layout Optional layout passed in shortcode attributes. - * @param string template Optional template passed in shortcode attributes. - * @return string - * - */ -function pmpro_advanced_levels_level_class( $level_id, $layout, $template ) { - - // The return variable. - $r = 'pmpro_level'; - - /** - * Allow custom code to filter the level output class. - * - * @param string layout Optional layout passed in shortcode attributes. - * @param string template Optional template passed in shortcode attributes. - * - */ - $r = apply_filters( 'pmpro_advanced_levels_level_class', $r, $level_id, $layout, $template ); - - return $r; -} - -/** - * Get the class for the inner div for each level item output. - * - * @param int level_id The ID of the level displayed. - * @param string layout Optional layout passed in shortcode attributes. - * @param string template Optional template passed in shortcode attributes. - * @param object current_level The current user's level object if set. - * @param int highlight The ID of the level to highlight if set. - * @return string - * - */ -function pmpro_advanced_levels_level_inner_class( $level_id, $layout, $template, $current_level, $highlight ) { - - // The return variable - $r = ''; - - if ( ! in_array( $layout, array( 'table', 'compare_table' ) ) ) { - $r .= ' entry post'; - } - - if ( $level_id == $current_level ) { - $r .= ' pmpro_level-current'; - } - - if ( $level_id == $highlight ) { - $r .= ' pmpro_level-highlight'; - } - - /** - * Allow custom code to filter the level output class. - * - * @param int level_id The ID of the level displayed. - * @param string layout Optional layout passed in shortcode attributes. - * @param string template Optional template passed in shortcode attributes. - * @param int current_level The current user's level ID if set. - * @param int highlight The ID of the level to highlight if set. - * - */ - $r = apply_filters( 'pmpro_advanced_levels_level_inner_class', $r, $level_id, $layout, $template, $current_level, $highlight ); - - return $r; -} - -/** - * Get the class for the inner div for each level item output. - * - * @param int level_id The ID of the level displayed. - * @param string layout Optional layout passed in shortcode attributes. - * @param string template Optional template passed in shortcode attributes. - * @param int current_level The current user's level ID if set. - * @return string - */ -function pmpro_advanced_levels_level_button_class( $level_id, $layout, $template, $current_level ) { - - // The return variable. - $r = 'pmpro_level_btn'; - - if ( in_array( $template, array( 'genesis', 'twentyfourteen', 'foundation' ) ) ) { - $r .= ' button'; - } elseif ( in_array( $template, array( 'gantry', 'bootstrap' ) ) ) { - $r .= ' btn btn-primary'; - } elseif ( $template === 'woothemes') { - $r .= ' woo-sc-button custom'; - } else { - $r .= ' pmpro_btn pmpro_btn-select'; - } - - // Show a disabled/greyed button that links to Account page. - if ( ! empty( $current_level ) && $level_id == $current_level->id ) { - // If it's a one-time-payment level or recurring level that's expiring soon, offer a link to renew. - if ( pmpro_isLevelExpiringSoon( $current_user->membership_level ) && $current_user->membership_level->allow_signups ) { - $r .= ' pmpro_btn-renew'; - } else { - $r .= ' pmpro_btn-disabled'; - } - } - - /** - * Allow custom code to filter the level output class. - * - * @param int level_id The ID of the level displayed. - * @param string layout Optional layout passed in shortcode attributes. - * @param string template Optional template passed in shortcode attributes. - * @param int current_level The current user's level ID if set. - * - */ - $r = apply_filters( 'pmpro_advanced_levels_level_button_class', $r, $level_id, $layout, $template, $current_level ); - - return $r; -} - -/** - * Get the button text for the checkout, renew, or account link for each level item output. - * - * @param int level_id The ID of the level displayed. - * @param object current_level The current user's level object if set. - * @param string checkout_button Text for checkout button passed in shortcode attributes. - * @param string renew_button Text for renew button passed in shortcode attributes. - * @param string account_button Text for account button passed in shortcode attributes. - * @return string - */ -function pmpro_advanced_levels_level_button_text( $level_id, $current_level, $checkout_button, $renew_button, $account_button ) { - - // The return variable. - $r = ''; - - if ( ! empty( $current_level ) && $level_id == $current_level->id ) { - // If it's a one-time-payment level, offer a link to renew. - if ( ! pmpro_isLevelRecurring( $current_level ) && ! empty( $current_user->membership_level->enddate ) ) { - $r = $renew_button; - } else { - $r = $account_button; - } - } else { - $r = $checkout_button; - } - - /** - * Allow custom code to filter the level button text. - * - * @param int level_id The ID of the level displayed. - * @param object current_level The current user's level object if set. - * @param string checkout_button Text for checkout button passed in shortcode attributes. - * @param string renew_button Text for renew button passed in shortcode attributes. - * @param string account_button Text for account button passed in shortcode attributes. - * - */ - $r = apply_filters( 'pmpro_advanced_levels_level_button_text', $r, $level_id, $current_level, $checkout_button, $renew_button, $account_button ); - - return $r; -} - -/** - * Build the href for the checkout, renew, or account link for each level item output. - * - * @param int level_id The ID of the level displayed. - * @param object current_level The current user's level object if set. - * @return string - */ -function pmpro_advanced_levels_level_button_link( $pmproal_link_arguments, $level_id, $current_level ) { - - // The return variable. - $r = ''; - - if ( ! empty( $current_level ) && $level_id == $current_level->id ) { - // If it's a one-time-payment level, offer a link to renew. - if ( ! pmpro_isLevelRecurring( $current_level ) && ! empty( $current_user->membership_level->enddate ) ) { - $r = add_query_arg( $pmproal_link_arguments, pmpro_url( 'checkout', null, 'https' ) ); - } else { - $r = add_query_arg( $pmproal_link_arguments, pmpro_url( 'account', null, 'https' ) ); - } - } else { - $r = add_query_arg( $pmproal_link_arguments, pmpro_url( 'checkout', null, 'https' ) ); - } - - /** - * Allow custom code to filter the level href. - * - * @param int level_id The ID of the level displayed. - * @param object current_level The current user's level object if set. - * - */ - $r = apply_filters( 'pmpro_advanced_levels_level_button_link', $r, $pmproal_link_arguments, $level_id, $current_level ); - - return $r; -} - -/** - * Function to add links to the plugin row meta - * - */ -function pmpro_advanced_levels_plugin_row_meta( $links, $file ) { - if ( strpos( $file, 'pmpro-advanced-levels-shortcode.php' ) !== false ) { - $new_links = array( - '' . __( 'Docs', 'pmpro-advanced-levels-shortcode' ) . '', - '' . __( 'Support', 'pmpro-advanced-levels-shortcode' ) . '', - ); - $links = array_merge($links, $new_links); - } - return $links; -} -add_filter( 'plugin_row_meta', 'pmpro_advanced_levels_plugin_row_meta', 10, 2 ); +id; + } + + $args = array( + 'post_type' => apply_filters( 'pmproal_level_landing_page_post_types', array( 'page', 'post' ) ), + 'meta_query' => array( + array( + 'key' => '_pmproal_landing_page_level', + 'value' => $level_id, + ) + ) + ); + + $posts = get_posts( $args ); + + if ( empty( $posts ) ) { + return false; + } else { + return $posts[0]; + } +} + +/** + * Get the class for the wrapping levels output div. + * + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @return string + * + */ +function pmpro_advanced_levels_wrapper_class( $layout, $template ) { + + // The return variable + $r = ''; + + // Get the class name for the chosen template, if available. + if ( ! empty( $template ) ) { + $r .= ' pmpro_advanced_levels-' . $template; + } + + // Add the class for the chosen layout, if available. + if ( ! empty( $layout ) ) { + if ( $layout == 'table' ) { + $r .= ' pmpro_advanced_levels-table'; + if ( $template === 'gantry' || $template === 'bootstrap' ) { + $r .= ' table table-striped table-bordered'; + } + } + + $r .= ' pmpro_levels-' . $layout; + } + + /** + * Allow custom code to filter the levels output class. + * + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_wrapper_class', $r, $layout, $template ); + + return $r; +} + +/** + * Get the class for the individual level item output. + * + * @param int level_id The ID of the level displayed. + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @return string + * + */ +function pmpro_advanced_levels_level_class( $level_id, $layout, $template ) { + + // The return variable. + $r = 'pmpro_level'; + + /** + * Allow custom code to filter the level output class. + * + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_level_class', $r, $level_id, $layout, $template ); + + return $r; +} + +/** + * Get the class for the inner div for each level item output. + * + * @param int level_id The ID of the level displayed. + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @param object current_level The current user's level object if set. + * @param int highlight The ID of the level to highlight if set. + * @return string + * + */ +function pmpro_advanced_levels_level_inner_class( $level_id, $layout, $template, $current_level, $highlight ) { + + // The return variable + $r = ''; + + if ( ! in_array( $layout, array( 'table', 'compare_table' ) ) ) { + $r .= ' entry post'; + } + + if ( $level_id == $current_level ) { + $r .= ' pmpro_level-current'; + } + + if ( $level_id == $highlight ) { + $r .= ' pmpro_level-highlight'; + } + + /** + * Allow custom code to filter the level output class. + * + * @param int level_id The ID of the level displayed. + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @param int current_level The current user's level ID if set. + * @param int highlight The ID of the level to highlight if set. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_level_inner_class', $r, $level_id, $layout, $template, $current_level, $highlight ); + + return $r; +} + +/** + * Get the class for the inner div for each level item output. + * + * @param int level_id The ID of the level displayed. + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @param int current_level The current user's level ID if set. + * @return string + */ +function pmpro_advanced_levels_level_button_class( $level_id, $layout, $template, $current_level ) { + + // The return variable. + $r = 'pmpro_level_btn'; + + if ( in_array( $template, array( 'genesis', 'twentyfourteen', 'foundation' ) ) ) { + $r .= ' button'; + } elseif ( in_array( $template, array( 'gantry', 'bootstrap' ) ) ) { + $r .= ' btn btn-primary'; + } elseif ( $template === 'woothemes') { + $r .= ' woo-sc-button custom'; + } else { + $r .= ' pmpro_btn pmpro_btn-select'; + } + + // Show a disabled/greyed button that links to Account page. + if ( ! empty( $current_level ) && $level_id == $current_level->id ) { + // If it's a one-time-payment level or recurring level that's expiring soon, offer a link to renew. + if ( pmpro_isLevelExpiringSoon( $current_user->membership_level ) && $current_user->membership_level->allow_signups ) { + $r .= ' pmpro_btn-renew'; + } else { + $r .= ' pmpro_btn-disabled'; + } + } + + /** + * Allow custom code to filter the level output class. + * + * @param int level_id The ID of the level displayed. + * @param string layout Optional layout passed in shortcode attributes. + * @param string template Optional template passed in shortcode attributes. + * @param int current_level The current user's level ID if set. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_level_button_class', $r, $level_id, $layout, $template, $current_level ); + + return $r; +} + +/** + * Get the button text for the checkout, renew, or account link for each level item output. + * + * @param int level_id The ID of the level displayed. + * @param object current_level The current user's level object if set. + * @param string checkout_button Text for checkout button passed in shortcode attributes. + * @param string renew_button Text for renew button passed in shortcode attributes. + * @param string account_button Text for account button passed in shortcode attributes. + * @return string + */ +function pmpro_advanced_levels_level_button_text( $level_id, $current_level, $checkout_button, $renew_button, $account_button ) { + + // The return variable. + $r = ''; + + if ( ! empty( $current_level ) && $level_id == $current_level->id ) { + // If it's a one-time-payment level, offer a link to renew. + if ( ! pmpro_isLevelRecurring( $current_level ) && ! empty( $current_user->membership_level->enddate ) ) { + $r = $renew_button; + } else { + $r = $account_button; + } + } else { + $r = $checkout_button; + } + + /** + * Allow custom code to filter the level button text. + * + * @param int level_id The ID of the level displayed. + * @param object current_level The current user's level object if set. + * @param string checkout_button Text for checkout button passed in shortcode attributes. + * @param string renew_button Text for renew button passed in shortcode attributes. + * @param string account_button Text for account button passed in shortcode attributes. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_level_button_text', $r, $level_id, $current_level, $checkout_button, $renew_button, $account_button ); + + return $r; +} + +/** + * Build the href for the checkout, renew, or account link for each level item output. + * + * @param int level_id The ID of the level displayed. + * @param object current_level The current user's level object if set. + * @return string + */ +function pmpro_advanced_levels_level_button_link( $pmproal_link_arguments, $level_id, $current_level ) { + + // The return variable. + $r = ''; + + if ( ! empty( $current_level ) && $level_id == $current_level->id ) { + // If it's a one-time-payment level, offer a link to renew. + if ( ! pmpro_isLevelRecurring( $current_level ) && ! empty( $current_user->membership_level->enddate ) ) { + $r = add_query_arg( $pmproal_link_arguments, pmpro_url( 'checkout', null, 'https' ) ); + } else { + $r = add_query_arg( $pmproal_link_arguments, pmpro_url( 'account', null, 'https' ) ); + } + } else { + $r = add_query_arg( $pmproal_link_arguments, pmpro_url( 'checkout', null, 'https' ) ); + } + + /** + * Allow custom code to filter the level href. + * + * @param int level_id The ID of the level displayed. + * @param object current_level The current user's level object if set. + * + */ + $r = apply_filters( 'pmpro_advanced_levels_level_button_link', $r, $pmproal_link_arguments, $level_id, $current_level ); + + return $r; +} + +/** + * Function to add links to the plugin row meta + * + */ +function pmpro_advanced_levels_plugin_row_meta( $links, $file ) { + if ( strpos( $file, 'pmpro-advanced-levels-shortcode.php' ) !== false ) { + $new_links = array( + '' . __( 'Docs', 'pmpro-advanced-levels-shortcode' ) . '', + '' . __( 'Support', 'pmpro-advanced-levels-shortcode' ) . '', + ); + $links = array_merge($links, $new_links); + } + return $links; +} +add_filter( 'plugin_row_meta', 'pmpro_advanced_levels_plugin_row_meta', 10, 2 ); diff --git a/readme.txt b/readme.txt index bd9b922..e5a1187 100644 --- a/readme.txt +++ b/readme.txt @@ -1,104 +1,104 @@ -=== Paid Memberships Pro - Advanced Levels Page Shortcode Add On === -Contributors: strangerstudios -Tags: pmpro, paid memberships pro, members, memberships, levels, templates, pricing, columns, themes -Requires at least: 3.5 -Tested up to: 4.7.4 -Stable tag: .2.4 - -An enhanced shortcode for customizing the display of your Membership Levels Page for Paid Memberships Pro. - -== Description == - -An enhanced shortcode for customizing the display of your Membership Levels Page for Paid Memberships Pro. - -Attributes in the [pmpro_advanced_levels] shortcode can be used to tweak how levels are displayed on the levels page, including options to display levels in a more HTML5-friendly div layout or popular column layouts. - -Also includes specific styling support for Bootstrap v3+, StudioPress/Genesis, Woo Themes, Gantry, and Foundation based themes as well as some of the default WP themes like TwentyFourteen. - -For more information, see add on documentation: -http://www.paidmembershipspro.com/add-ons/plus-add-ons/pmpro-advanced-levels-shortcode/ - -== Installation == - -1. Upload the `pmpro-advanced-levels` folder to the `/wp-content/plugins/` directory. -1. Activate the plugin through the 'Plugins' menu in WordPress. -1. Replace the [pmpro_levels] shortcode on your site with a [pmpro_advanced_levels] one. - -Here is an example of the pmpro_advanced_levels shortcode with all attributes. - -[pmpro_advanced_levels template="genesis" levels="1,2,3" layout="table" hightlight="2" description="false" checkout_button="Register Now"] - -For more information, see our blog post here: -http://www.paidmembershipspro.com/2015/02/new-plugin-with-advanced-options-for-membership-levels-page-display/ - -== Changelog == -= .2.4 = -* ENHANCEMENT: Added pmproal_before_level hook to the div/column layouts. -* ENHANCEMENT: Added pmproal_after_level hook to the div/column layouts. -* ENHANCEMENT: Added pmproal_extra_cols_before_header hook to the table layout. -* ENHANCEMENT: Added pmproal_extra_cols_after_header hook to the table layout. -* ENHANCEMENT: Added pmproal_extra_cols_before_body hook to the table layout. -* ENHANCEMENT: Added pmproal_extra_cols_after_body hook to the table layout. - -= .2.3 = -* BUG FIX: Make Read More text translatable -* BUG FIX: Whitescreen in Conmparison table template (Thanks, BingoTheIguana on GitHub) -* BUG FIX: Incorrect function name on init -* BUG FIX/ENHANCEMENT: Glotpress updates (pmproal -> pmpro-advanced-levels-shortcode) -* BUG FIX/ENHANCEMENT: Use standard WordPress URL builder -* BUG FIX/ENHANCEMENT: Include discount code in all checkout page destination URLs -* BUG FIX/ENHANCEMENT: Glotpress update (renamed translation files) -* BUG FIX/ENHANCEMENT: Use array and add_query_arg() for all checkout page links and include discount code if specified -* ENHANCEMENT: Add pmproal_before_template_load action - -= .2.2 = -* BUG FIX: Fixed some strings that needed to be wrapped for translation. -* BUG FIX/ENHANCEMENT: Now honoring the "Disable New Signups" option on the edit membership levels page. If checked, the level will be excluded from lists generated by the shortcode. -* ENHANCEMENT: Updating stylesheet for WordPress 4.7 and new Twenty Seventeen theme support. -* ENHANCEMENT: Added Spanish translation. (Thanks, David A. Lareo) -* ENHANCEMENT: Added French translation. (Thanks, paramedicquebec on GitHub) - -= .2.1 = -* ENHANCEMENT: Moving all individual layouts into separate template files. -* BUG: Fixed responsive layout for small screens when using 2, 3, or 4 columns. - -= .2 = -* BUG: Fixed highlight and current level classes in compare_table layout. -* BUG: Fixed notice in compare_table layout. -* ENHANCEMENT: Added responsive support for compare_table layout. Layout now collapses to a single column div-type layout with comparison attributes for device width < 767px. - -= .1.8.2 = -* Fixed navigation clearing issue for Genesis layout option. -* Added translation support to add-on and included Norwegian translation files. - -= .1.8.1 = -* Fixed bug if first level column of compare_table was highlight. - -= .1.8 = -* Added support for Levels Comparison Table layout type (ex. layout="compare_table"). -* Added shortcode attribute for renew_button text. - -= .1.7 = -* Added support for Bootstrap v3+ based themes. - -= .1.6 = -* Fixed bug where the current level CSS class wasn't always set correctly on elements. - -= .1.5 = -* Now applying the pmpro_levels_array filter to the array of levels when the levels are specified in a shortcode attribute. If you are using the pmpro_advanced_levels shortcode AND the pmpro_levels_array filter already, make sure your filter is programmed to account for this (perhaps by checking the globsl $post->ID to only run on certain pages/et). (Thanks, Camouyer) - -= .1.4 = -* Fixed bug where discount codes were not being embedded in the checkout link URLs when added to the shortcake. (Thanks, 3fingas) - -= .1.3 = -* If no specific levels are passed in the pmpro_levels_array filter is applied to the levels. - -= .1.2 = -* Some more style updates. - -= .1.1 = -* Fixed some PHP warnings that were affecting layout and some CSS styles were tweaked. -* Fixed enqueue of CSS to work for different plugin directory names. - -= .1 = -* First version. +=== Paid Memberships Pro - Advanced Levels Page Shortcode Add On === +Contributors: strangerstudios +Tags: pmpro, paid memberships pro, members, memberships, levels, templates, pricing, columns, themes +Requires at least: 3.5 +Tested up to: 4.7.4 +Stable tag: .2.4 + +An enhanced shortcode for customizing the display of your Membership Levels Page for Paid Memberships Pro. + +== Description == + +An enhanced shortcode for customizing the display of your Membership Levels Page for Paid Memberships Pro. + +Attributes in the [pmpro_advanced_levels] shortcode can be used to tweak how levels are displayed on the levels page, including options to display levels in a more HTML5-friendly div layout or popular column layouts. + +Also includes specific styling support for Bootstrap v3+, StudioPress/Genesis, Woo Themes, Gantry, and Foundation based themes as well as some of the default WP themes like TwentyFourteen. + +For more information, see add on documentation: +http://www.paidmembershipspro.com/add-ons/plus-add-ons/pmpro-advanced-levels-shortcode/ + +== Installation == + +1. Upload the `pmpro-advanced-levels` folder to the `/wp-content/plugins/` directory. +1. Activate the plugin through the 'Plugins' menu in WordPress. +1. Replace the [pmpro_levels] shortcode on your site with a [pmpro_advanced_levels] one. + +Here is an example of the pmpro_advanced_levels shortcode with all attributes. + +[pmpro_advanced_levels template="genesis" levels="1,2,3" layout="table" hightlight="2" description="false" checkout_button="Register Now"] + +For more information, see our blog post here: +http://www.paidmembershipspro.com/2015/02/new-plugin-with-advanced-options-for-membership-levels-page-display/ + +== Changelog == += .2.4 = +* ENHANCEMENT: Added pmproal_before_level hook to the div/column layouts. +* ENHANCEMENT: Added pmproal_after_level hook to the div/column layouts. +* ENHANCEMENT: Added pmproal_extra_cols_before_header hook to the table layout. +* ENHANCEMENT: Added pmproal_extra_cols_after_header hook to the table layout. +* ENHANCEMENT: Added pmproal_extra_cols_before_body hook to the table layout. +* ENHANCEMENT: Added pmproal_extra_cols_after_body hook to the table layout. + += .2.3 = +* BUG FIX: Make Read More text translatable +* BUG FIX: Whitescreen in Conmparison table template (Thanks, BingoTheIguana on GitHub) +* BUG FIX: Incorrect function name on init +* BUG FIX/ENHANCEMENT: Glotpress updates (pmproal -> pmpro-advanced-levels-shortcode) +* BUG FIX/ENHANCEMENT: Use standard WordPress URL builder +* BUG FIX/ENHANCEMENT: Include discount code in all checkout page destination URLs +* BUG FIX/ENHANCEMENT: Glotpress update (renamed translation files) +* BUG FIX/ENHANCEMENT: Use array and add_query_arg() for all checkout page links and include discount code if specified +* ENHANCEMENT: Add pmproal_before_template_load action + += .2.2 = +* BUG FIX: Fixed some strings that needed to be wrapped for translation. +* BUG FIX/ENHANCEMENT: Now honoring the "Disable New Signups" option on the edit membership levels page. If checked, the level will be excluded from lists generated by the shortcode. +* ENHANCEMENT: Updating stylesheet for WordPress 4.7 and new Twenty Seventeen theme support. +* ENHANCEMENT: Added Spanish translation. (Thanks, David A. Lareo) +* ENHANCEMENT: Added French translation. (Thanks, paramedicquebec on GitHub) + += .2.1 = +* ENHANCEMENT: Moving all individual layouts into separate template files. +* BUG: Fixed responsive layout for small screens when using 2, 3, or 4 columns. + += .2 = +* BUG: Fixed highlight and current level classes in compare_table layout. +* BUG: Fixed notice in compare_table layout. +* ENHANCEMENT: Added responsive support for compare_table layout. Layout now collapses to a single column div-type layout with comparison attributes for device width < 767px. + += .1.8.2 = +* Fixed navigation clearing issue for Genesis layout option. +* Added translation support to add-on and included Norwegian translation files. + += .1.8.1 = +* Fixed bug if first level column of compare_table was highlight. + += .1.8 = +* Added support for Levels Comparison Table layout type (ex. layout="compare_table"). +* Added shortcode attribute for renew_button text. + += .1.7 = +* Added support for Bootstrap v3+ based themes. + += .1.6 = +* Fixed bug where the current level CSS class wasn't always set correctly on elements. + += .1.5 = +* Now applying the pmpro_levels_array filter to the array of levels when the levels are specified in a shortcode attribute. If you are using the pmpro_advanced_levels shortcode AND the pmpro_levels_array filter already, make sure your filter is programmed to account for this (perhaps by checking the globsl $post->ID to only run on certain pages/et). (Thanks, Camouyer) + += .1.4 = +* Fixed bug where discount codes were not being embedded in the checkout link URLs when added to the shortcake. (Thanks, 3fingas) + += .1.3 = +* If no specific levels are passed in the pmpro_levels_array filter is applied to the levels. + += .1.2 = +* Some more style updates. + += .1.1 = +* Fixed some PHP warnings that were affecting layout and some CSS styles were tweaked. +* Fixed enqueue of CSS to work for different plugin directory names. + += .1 = +* First version. diff --git a/templates/levels-compare_table.php b/templates/levels-compare_table.php index e6fcdc6..b50e44e 100644 --- a/templates/levels-compare_table.php +++ b/templates/levels-compare_table.php @@ -1,478 +1,478 @@ - -
pmpro_advanced_levels-compare_table"> - - - - - - - - - - - - - - - - - - - - - - - - - - id ); - - $pmproal_link_arguments['level'] = $level->id; - ?> - - - - - - - - = 0 && !empty($numeric_levels_array[$count])) - $level = $numeric_levels_array[$count]; - else - $level = NULL; - $count++; - ?> - - - - - - - - - id; - - $current_level = pmpro_hasMembershipLevel( $level->id ); - ?> - - - - - - - - - - - - - - - - - - - - -
-

name?>

-
- - - - - -
- -
  - membership_level->ID)) { ?> - " href=""> - - " href=""> - - membership_level) && $current_user->membership_level->allow_signups ) { ?> - " href=""> - - " href=""> - - -
- '; } - elseif($compareitem_value == '0') { echo ''; } - else { echo $compareitem_value; } - ?> -
  - membership_level->ID)) { ?> - " href=""> - - " href=""> - - membership_level) && !empty($current_user->membership_level->enddate)) - { - ?> - " href=""> - - " href=""> - - -
- -
id); - } else { - $level_page = null; - - } - - if(!empty($level_page)) - { - ?> - - -
-
pmpro_advanced_levels-compare_table_responsive"> -id; - - $count++; - $current_level = pmpro_hasMembershipLevel( $level->id ); - ?> -
-
id) { echo "pmpro_level-highlight "; } if($template === "gantry") { echo " well"; } if($template === "bootstrap") { echo " panel panel-default"; } ?>"> - class="entry-header">>name?> - - -
- - -
- -

"> - - - - - - -

- -

- - - description)) { ?> - class="entry-content"> - description); ?> -
- - '; - foreach($compareitems as $compareitem) - { - $compareitem_values = explode(",", $compareitem); - if($count >= 0 && !empty($numeric_levels_array[$count])) - $compare_level = $numeric_levels_array[$count]; - else - $compare_level = NULL; - if($compareitem_values[$count] != '0') - { - if($compareitem_values[$count] == '1') - { - echo ' ' . $compareitem_values[0] . ''; - } - else - { - echo ' ' . $compareitem_values[0] . ': '; - echo $compareitem_values[$count]; - } - echo '
'; - } - } - echo '

'; - } - ?> - class="entry-footer"> - -
- -
- - + +pmpro_advanced_levels-compare_table"> + + + + + + + + + + + + + + + + + + + + + + + + + + id ); + + $pmproal_link_arguments['level'] = $level->id; + ?> + + + + + + + + = 0 && !empty($numeric_levels_array[$count])) + $level = $numeric_levels_array[$count]; + else + $level = NULL; + $count++; + ?> + + + + + + + + + id; + + $current_level = pmpro_hasMembershipLevel( $level->id ); + ?> + + + + + + + + + + + + + + + + + + + + +
+

name?>

+
+ + + + + +
+ +
  + membership_level->ID)) { ?> + " href=""> + + " href=""> + + membership_level) && $current_user->membership_level->allow_signups ) { ?> + " href=""> + + " href=""> + + +
+ '; } + elseif($compareitem_value == '0') { echo ''; } + else { echo $compareitem_value; } + ?> +
  + membership_level->ID)) { ?> + " href=""> + + " href=""> + + membership_level) && !empty($current_user->membership_level->enddate)) + { + ?> + " href=""> + + " href=""> + + +
+ +
id); + } else { + $level_page = null; + + } + + if(!empty($level_page)) + { + ?> + + +
+
pmpro_advanced_levels-compare_table_responsive"> +id; + + $count++; + $current_level = pmpro_hasMembershipLevel( $level->id ); + ?> +
+
id) { echo "pmpro_level-highlight "; } if($template === "gantry") { echo " well"; } if($template === "bootstrap") { echo " panel panel-default"; } ?>"> + class="entry-header">>name?> + + +
+ + +
+ +

"> + + + + + + +

+ +

+ + + description)) { ?> + class="entry-content"> + description); ?> +
+ + '; + foreach($compareitems as $compareitem) + { + $compareitem_values = explode(",", $compareitem); + if($count >= 0 && !empty($numeric_levels_array[$count])) + $compare_level = $numeric_levels_array[$count]; + else + $compare_level = NULL; + if($compareitem_values[$count] != '0') + { + if($compareitem_values[$count] == '1') + { + echo ' ' . $compareitem_values[0] . ''; + } + else + { + echo ' ' . $compareitem_values[0] . ': '; + echo $compareitem_values[$count]; + } + echo '
'; + } + } + echo '

'; + } + ?> + class="entry-footer"> + +
+ +
+ + diff --git a/templates/levels-div.php b/templates/levels-div.php index d9d32c3..a44a048 100644 --- a/templates/levels-div.php +++ b/templates/levels-div.php @@ -1,63 +1,63 @@ - -
-id ); - - foreach( $pmpro_levels_filtered as $level ) { - $pmproal_link_arguments['level'] = $level->id; - ?> -
- -
- - id, $layout ); ?> - -

name; ?>

- - -
- description ); ?> -
- - - id, $current_level, $checkout_button, $renew_button, $account_button ); ?> - - - - - - - - - - - - - - - - id, $layout ); ?> -
-
- -
+ +
+id ); + + foreach( $pmpro_levels_filtered as $level ) { + $pmproal_link_arguments['level'] = $level->id; + ?> +
+ +
+ + id, $layout ); ?> + +

name; ?>

+ + +
+ description ); ?> +
+ + + id, $current_level, $checkout_button, $renew_button, $account_button ); ?> + + + + + + + + + + + + + + + + id, $layout ); ?> +
+
+ +
diff --git a/templates/levels-table.php b/templates/levels-table.php index 2ccd474..2dfda79 100644 --- a/templates/levels-table.php +++ b/templates/levels-table.php @@ -1,79 +1,79 @@ - - - - - - - - - - - - - - - - - -id; - $current_level = pmpro_hasMembershipLevel( $level->id ); - ?> - - - id, $template ); ?> - - - - - - - - - - - - - - id, $template ); ?> - - - - -
 
-

name; ?>

- -
- description ); ?> -
- -
- - - - - id, $current_level, $checkout_button, $renew_button, $account_button ); ?> -
+ + + + + + + + + + + + + + + + + +id; + $current_level = pmpro_hasMembershipLevel( $level->id ); + ?> + + + id, $template ); ?> + + + + + + + + + + + + + + id, $template ); ?> + + + + +
 
+

name; ?>

+ +
+ description ); ?> +
+ +
+ + + + + id, $current_level, $checkout_button, $renew_button, $account_button ); ?> +
diff --git a/templates/levels.php b/templates/levels.php index c900752..555066e 100644 --- a/templates/levels.php +++ b/templates/levels.php @@ -1,197 +1,197 @@ - __('Your Level', 'pmpro-advanced-levels-shortcode'), - 'back_link' => '1', - 'compare' => NULL, - 'template' => NULL, - 'checkout_button' => __('Select', 'pmpro-advanced-levels-shortcode'), - 'description' => '1', - 'discount_code' => NULL, - 'expiration' => '1', - 'highlight' => NULL, - 'layout' => 'div', - 'levels' => NULL, - 'more_button' => NULL, - 'price' => 'short', - 'renew_button' => __('Renew', 'pmpro-advanced-levels-shortcode'), - 'template' => NULL, - ), $atts)); - - global $wpdb, $pmpro_msg, $pmpro_msgt, $current_user, $pmpro_currency_symbol, $pmpro_all_levels, $pmpro_visible_levels, $current_user, $membership_levels; - - if($back_link === "0" || $back_link === "false" || $back_link === "no") - $back_link = false; - else - $back_link = true; - - if($compare === "0" || $compare === "false" || $compare === "no") - $compare = false; - else - $compareitems = explode(";", $compare); - - //turn 0's into falses - if($description === "0" || $description === "false" || $description === "no") - $description = false; - else - $description = true; - - if($expiration === "0" || $expiration === "false" || $expiration === "no") - $expiration = false; - else - $expiration = true; - - if($more_button === "0" || $more_button === "false" || $more_button === "no" || empty($more_button)) - $more_button = false; - elseif($more_button === "1" || $more_button === "true" || $more_button === "yes") - $more_button = __( "Read More", "pmpro-advanced-levels-shortcode" ); - - if($price === "0" || $price === "false" || $price === "hide") - $show_price = false; - else - $show_price = true; - - //string to store other params to add to the checkout url - $checkout_url_params = ""; - - ob_start(); - - //make sure pmpro_levels has all levels - if ( ! isset( $pmpro_all_levels ) ) { - $pmpro_all_levels = pmpro_getAllLevels( false, true ); - } - - if($pmpro_msg) - { - ?> -
- id == $level_id && true == $level->allow_signups) - { - $pmpro_levels_filtered[$level->id] = $level; - break; - } - } - } - } else { - $pmpro_level_order = pmpro_getOption( 'level_order' ); - $levels_order = explode( ',', $pmpro_level_order ); - - // Reorder array - foreach ( $levels_order as $level_id ) { - foreach ( $pmpro_all_levels as $key => $level ) { - if ( $level_id == $level->id ) { - $pmpro_levels_filtered[] = $pmpro_all_levels[$key]; - } - } - } - } - - $pmpro_levels_filtered = apply_filters("pmpro_levels_array", $pmpro_levels_filtered); - $numeric_levels_array = array_values($pmpro_levels_filtered); - - //Allows you to add ?discount_code=code to your URL - if( !empty( $_REQUEST['discount_code'] ) ){ - $discount_code = sanitize_text_field( $_REQUEST['discount_code'] ); - } - - //update per discount code - if(!empty($discount_code) && !empty($pmpro_levels_filtered)) - { - foreach($pmpro_levels_filtered as $level_id => $level) - { - //check code for this level and update if applicable - if(pmpro_checkDiscountCode($discount_code, $level->id)) - { - $pmproal_link_arguments['discount_code'] = $discount_code; - - $sqlQuery = "SELECT l.id, cl.*, l.name, l.description, l.allow_signups FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id LEFT JOIN $wpdb->pmpro_discount_codes dc ON dc.id = cl.code_id WHERE dc.code = '" . $discount_code . "' AND cl.level_id = '" . (int)$level->id . "' LIMIT 1"; - $pmpro_levels_filtered[$level_id] = $wpdb->get_row($sqlQuery); - $pmpro_levels_filtered[$level_id]->base_level = $level; - - } - } - } - - do_action('pmproal_before_template_load' ); - - if($layout == 'table') - { - //load template for layout = "table" - - include("levels-table.php"); - } - elseif($layout == 'compare_table') - { - //load template for layout = "compare_table" - include("levels-compare_table.php"); - } - else - { - //load template for layout = "div", "2col", "3col", "4col" or unspecified layout attribute - include("levels-div.php"); - } - ?> - '; } ?> - - - '; } ?> - - $1", $text); - - //return - return $level_cost; -} + __('Your Level', 'pmpro-advanced-levels-shortcode'), + 'back_link' => '1', + 'compare' => NULL, + 'template' => NULL, + 'checkout_button' => __('Select', 'pmpro-advanced-levels-shortcode'), + 'description' => '1', + 'discount_code' => NULL, + 'expiration' => '1', + 'highlight' => NULL, + 'layout' => 'div', + 'levels' => NULL, + 'more_button' => NULL, + 'price' => 'short', + 'renew_button' => __('Renew', 'pmpro-advanced-levels-shortcode'), + 'template' => NULL, + ), $atts)); + + global $wpdb, $pmpro_msg, $pmpro_msgt, $current_user, $pmpro_currency_symbol, $pmpro_all_levels, $pmpro_visible_levels, $current_user, $membership_levels; + + if($back_link === "0" || $back_link === "false" || $back_link === "no") + $back_link = false; + else + $back_link = true; + + if($compare === "0" || $compare === "false" || $compare === "no") + $compare = false; + else + $compareitems = explode(";", $compare); + + //turn 0's into falses + if($description === "0" || $description === "false" || $description === "no") + $description = false; + else + $description = true; + + if($expiration === "0" || $expiration === "false" || $expiration === "no") + $expiration = false; + else + $expiration = true; + + if($more_button === "0" || $more_button === "false" || $more_button === "no" || empty($more_button)) + $more_button = false; + elseif($more_button === "1" || $more_button === "true" || $more_button === "yes") + $more_button = __( "Read More", "pmpro-advanced-levels-shortcode" ); + + if($price === "0" || $price === "false" || $price === "hide") + $show_price = false; + else + $show_price = true; + + //string to store other params to add to the checkout url + $checkout_url_params = ""; + + ob_start(); + + //make sure pmpro_levels has all levels + if ( ! isset( $pmpro_all_levels ) ) { + $pmpro_all_levels = pmpro_getAllLevels( false, true ); + } + + if($pmpro_msg) + { + ?> +
+ id == $level_id && true == $level->allow_signups) + { + $pmpro_levels_filtered[$level->id] = $level; + break; + } + } + } + } else { + $pmpro_level_order = pmpro_getOption( 'level_order' ); + $levels_order = explode( ',', $pmpro_level_order ); + + // Reorder array + foreach ( $levels_order as $level_id ) { + foreach ( $pmpro_all_levels as $key => $level ) { + if ( $level_id == $level->id ) { + $pmpro_levels_filtered[] = $pmpro_all_levels[$key]; + } + } + } + } + + $pmpro_levels_filtered = apply_filters("pmpro_levels_array", $pmpro_levels_filtered); + $numeric_levels_array = array_values($pmpro_levels_filtered); + + //Allows you to add ?discount_code=code to your URL + if( !empty( $_REQUEST['discount_code'] ) ){ + $discount_code = sanitize_text_field( $_REQUEST['discount_code'] ); + } + + //update per discount code + if(!empty($discount_code) && !empty($pmpro_levels_filtered)) + { + foreach($pmpro_levels_filtered as $level_id => $level) + { + //check code for this level and update if applicable + if(pmpro_checkDiscountCode($discount_code, $level->id)) + { + $pmproal_link_arguments['discount_code'] = $discount_code; + + $sqlQuery = "SELECT l.id, cl.*, l.name, l.description, l.allow_signups FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id LEFT JOIN $wpdb->pmpro_discount_codes dc ON dc.id = cl.code_id WHERE dc.code = '" . $discount_code . "' AND cl.level_id = '" . (int)$level->id . "' LIMIT 1"; + $pmpro_levels_filtered[$level_id] = $wpdb->get_row($sqlQuery); + $pmpro_levels_filtered[$level_id]->base_level = $level; + + } + } + } + + do_action('pmproal_before_template_load' ); + + if($layout == 'table') + { + //load template for layout = "table" + + include("levels-table.php"); + } + elseif($layout == 'compare_table') + { + //load template for layout = "compare_table" + include("levels-compare_table.php"); + } + else + { + //load template for layout = "div", "2col", "3col", "4col" or unspecified layout attribute + include("levels-div.php"); + } + ?> + '; } ?> + + + '; } ?> + + $1", $text); + + //return + return $level_cost; +} From 23cca58b1e64979e1d1e3a75cd87518a7f025fa6 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Thu, 15 Oct 2020 07:25:08 -0400 Subject: [PATCH 05/17] Adding fancy readme for Github; Readme improvements. --- .gitattributes | 6 +++ .github/CONTRIBUTING.md | 49 +++++++++++++++++++++ .github/ISSUE_TEMPLATE.MD | 45 +++++++++++++++++++ .github/ISSUE_TEMPLATE/bug_report.md | 36 +++++++++++++++ .github/ISSUE_TEMPLATE/enhancement.md | 21 +++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 21 +++++++++ .github/ISSUE_TEMPLATE/support.md | 20 +++++++++ .github/PULL_REQUEST_TEMPLATE.MD | 32 ++++++++++++++ .gitignore | 49 --------------------- README.md | 42 ++++++++++++++++++ pmpro-advanced-levels-shortcode-banner.jpg | Bin 0 -> 45021 bytes pmpro-advanced-levels-shortcode.php | 16 +++---- readme.txt | 15 ++++--- 13 files changed, 288 insertions(+), 64 deletions(-) create mode 100644 .gitattributes create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE.MD create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/enhancement.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/support.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.MD delete mode 100644 .gitignore create mode 100644 README.md create mode 100644 pmpro-advanced-levels-shortcode-banner.jpg diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..44c72fc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +# Items to ignore when downloading a zip +pmpro-advanced-levels-shortcode-banner.jpg export-ignore +.gitattributes export-ignore +.github export-ignore +README.md export-ignore +languages/gettext.sh export-ignore \ No newline at end of file diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..0ce6071 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,49 @@ +# Contribute to Paid Memberships Pro + +Paid Memberships Pro is the "community solution" for membership sites on WordPress, and so contributions of all kinds are appreciated. + +When contributing, please follow these guidelines to ensure things work as smoothly as possible. + +__Please Note:__ GitHub is for bug reports and contributions only. If you have a support or customization question, go to our [Member Support Page](https://www.paidmembershipspro.com/support/) instead. + +## Getting Started + +* __Do not report potential security vulnerabilities here. Email them privately to [info@paidmembershipspro.com](mailto:info@paidmembershipspro.com) with the words "Security Vulnerability" in the subject.__ +* Submit a ticket for your issue, assuming one does not already exist. + * Raise it on our [Issue Tracker](https://github.com/strangerstudios/pmpro-advanced-levels-page-shortcode/issues/new/choose) + * Clearly describe the issue including steps to reproduce the bug. + * Make sure you fill in the earliest version that you know has the issue as well as the version of WordPress you're using. + +## Making Changes + +* Fork the repository on GitHub +* For bug fixes, checkout the DEV branch of the PMPro repository. +* For new features and enhancements, checkout the branch for the version the feature is milestoned for. +* Make sure to pull in any "upstream" changes first. + * Use `git remote add upstream https://github.com/strangerstudios/pmpro-advanced-levels-page-shortcode.git` to set the upstream repo + * Use `git checkout dev` to get on the development branch. + * Use `git pull upstream dev` to get the latest updates. + * Use `git push` to push those updates to your fork. +* Create a new local branch for each separate bug fix or feature. This will ensure that each pull request is for one issue only and easier to process. + * Use `git checkout -b nameofmybugfixorfeature` to create the new branch +* Make the changes to your local repository. +* Ensure you stick to the [WordPress Coding Standards](https://codex.wordpress.org/WordPress_Coding_Standards) (even though much of the PMPro code does not currently) +* If you have an automatic beautifier in your IDE or dev environment, turn it off. Unrelated style changes in your pull requests will make them harder to process. Feel free to message the core development team to ask them to clean up a file you are working on if the inconsitent coding styles is bothering you. +* You can update the readme.txt to include a comment about your fix or feature in the changelog, but if you do not the core team will do it for you. +* When committing, reference your issue (if present) and include a note about the fix in the commit message. +* Push the changes to your fork. +* For bug fixes, submit a pull request to the DEV branch of the PMPro repository. +* For new features and enhancements, submit a pull request to the version the feature is milestoned for. This will usually be the version number following the current release unless the core dev team has milestoned the feature for a later release. +* We will process all pull requests and make suggestions or changes as soon as possible. Feel free to ping us politely via email or social networks to take a look at your pulls. + +## Code Documentation + +* We would like for every function, filter, class, and class method to be documented using phpDoc standards. +* An example of [how PMPro uses phpDoc blocks can be found here](https://gist.github.com/sunnyratilal/5308969). +* Please make sure that every function is documented so that when we update our API Documentation things don't go awry! + * If you're adding/editing a function in a class, make sure to add `@access {private|public|protected}` +* Finally, please use tabs and not spaces. The tab indent size should be 4 for all Paid Memberships Pro code. + +# Additional Resources +* [General GitHub Documentation](https://help.github.com/) +* [GitHub Pull Request documentation](https://help.github.com/send-pull-requests/) diff --git a/.github/ISSUE_TEMPLATE.MD b/.github/ISSUE_TEMPLATE.MD new file mode 100644 index 0000000..2a43f4c --- /dev/null +++ b/.github/ISSUE_TEMPLATE.MD @@ -0,0 +1,45 @@ + + + + + + + + +## Prerequisites + + + +- [ ] I have searched for similar issues in both open and closed tickets and cannot find a duplicate. +- [ ] The issue still exists against the latest `dev` branch of Paid Memberships Pro on Github (this is **not** the same version as on WordPress.org!) +- [ ] I have attempted to find the simplest possible steps to reproduce the issue + +## Steps to reproduce the issue + + + +1. +2. +3. + +## Expected/actual behavior + +When I follow those steps, I see... + +I was expecting to see... + +## Isolating the problem + + + +- [ ] This bug happens with only Paid Memberships Pro plugin active +- [ ] This bug happens with a default WordPress theme active, or [Memberlite](https://wordpress.org/themes/memberlite/) +- [ ] I can reproduce this bug consistently using the steps above + +## WordPress Environment + +
+``` +Please share non-sensitive information about your hosting environment such as WordPress version, PHP version, Paid Memberships Pro and any related plugins versions. +``` +
\ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..35cbd3c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,36 @@ +--- +name: "🐛 Bug Report" +about: Report a bug if something isn't working as expected in Paid Memberships Pro. +title: '' +labels: 'bug' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. Please be as descriptive as possible; issues lacking detail, or for any other reason than to report a bug, may be closed or left unattended. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Screenshots** +If applicable, please attach a screenshot to make your issue clearer. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Isolating the problem (mark completed items with an [x]):** +- [ ] I have deactivated other plugins and confirmed this bug occurs when only Paid Memberships Pro plugin is active. +- [ ] This bug happens with a default WordPress theme active, or [Memberlite](https://wordpress.org/themes/memberlite/). +- [ ] I can reproduce this bug consistently using the steps above. + +**WordPress Environment** +
+``` +Please share non-sensitive information about your hosting environment such as WordPress version, PHP version, Paid Memberships Pro and any related plugins versions. +``` +
diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md new file mode 100644 index 0000000..65c7905 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/enhancement.md @@ -0,0 +1,21 @@ +--- +name: "⭐️ Enhancement" +about: If you have an idea to improve an existing feature or need something + for development (such as a new hook) please let us know or submit a Pull Request. +title: '' +labels: 'enhancement' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +If applicable, add any other context or screenshots about the enhancement here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..c2c5816 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,21 @@ +--- +name: "➕ Feature Request" +about: "Suggest a new feature. We'll consider building it if it receives + sufficient interest!" +title: '' +labels: 'feature request' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +If applicable, add any other context or screenshots about your feature request here. diff --git a/.github/ISSUE_TEMPLATE/support.md b/.github/ISSUE_TEMPLATE/support.md new file mode 100644 index 0000000..74bb3d4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/support.md @@ -0,0 +1,20 @@ +--- +name: "💬 Support Question" +about: "If you have a question, please see our docs or use our helpdesk." +title: '' +labels: 'Type: support' +assignees: '' + +--- + +We don't offer technical support on GitHub so we recommend using the following: + +**Reading our documentation** +Usage docs can be found here: https://www.paidmembershipspro.com/documentation/ + +**Technical support for premium extensions or if you're a Paid Memberships Pro Plus member** +Submit a ticket on our helpdesk by visiting https://www.paidmembershipspro.com/new-topic/ (Please note that an [active membership] (https://www.paidmembershipspro.com/pricing) is required for paid support.) + +**General usage and development questions** +- WordPress.org Forums: https://wordpress.org/support/plugin/paid-memberships-pro +- Website: https://www.paidmembershipspro.com/contact/ diff --git a/.github/PULL_REQUEST_TEMPLATE.MD b/.github/PULL_REQUEST_TEMPLATE.MD new file mode 100644 index 0000000..b7006d7 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.MD @@ -0,0 +1,32 @@ +### All Submissions: + +* [ ] Have you followed the [Contributing guidelines](https://github.com/strangerstudios/pmpro-advanced-levels-page-shortcode/blob/dev/.github/CONTRIBUTING.md)? +* [ ] Does your code follow the [WordPress' coding standards](https://make.wordpress.org/core/handbook/best-practices/coding-standards/)? +* [ ] Have you checked to ensure there aren't other open [Pull Requests](https://github.com/strangerstudios/pmpro-advanced-levels-page-shortcode/pulls/) for the same update/change? + + + + + +### Changes proposed in this Pull Request: + + + +Resolves XXX. + +### How to test the changes in this Pull Request: + +1. +2. +3. + +### Other information: + +* [ ] Have you added an explanation of what your changes do and why you'd like us to include them? +* [ ] Have you successfully run tests with your changes locally? + + + +### Changelog entry + +> Enter a summary of all changes on this Pull Request. This will appear in the changelog if accepted. diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0660146..0000000 --- a/.gitignore +++ /dev/null @@ -1,49 +0,0 @@ -# Created by .ignore support plugin (hsz.mobi) -### JetBrains template -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio - -*.iml - -## Directory-based project format: -.idea/ -# if you remove the above rule, at least ignore the following: - -# User-specific stuff: -# .idea/workspace.xml -# .idea/tasks.xml -# .idea/dictionaries - -# Sensitive or high-churn files: -# .idea/dataSources.ids -# .idea/dataSources.xml -# .idea/sqlDataSources.xml -# .idea/dynamic.xml -# .idea/uiDesigner.xml - -# Gradle: -# .idea/gradle.xml -# .idea/libraries - -# Mongo Explorer plugin: -# .idea/mongoSettings.xml - -## File-based project format: -*.ipr -*.iws - -## Plugin-specific files: - -# IntelliJ -/out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties - diff --git a/README.md b/README.md new file mode 100644 index 0000000..0709ab5 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +![](pmpro-advanced-levels-shortcode-banner.jpg) + +# [Paid Memberships Pro - Advanced Levels Page Shortcode](https://www.paidmembershipspro.com/add-ons/pmpro-advanced-levels-shortcode/) # +[comment]: # (Generate badges from shields.io, only works for .org plugins to get other stats etc. We'd have to create our own endpoints for Premium plugins) + +![License](https://img.shields.io/badge/license-GPL--2.0%2B-red.svg?style=flat-square) + +### Welcome to the Paid Memberships Pro - Advanced Levels Page Shortcode GitHub Repository + +This plugin activates a new shortcode with many attributes to customize the levels page or to display level offerings and pricing tables anywhere on your membership site. The shortcode also includes support for widely used theme frameworks/parent themes. + +Here is an example of the enhanced shortcode this Add On includes: + +`[pmpro_advanced_levels levels="1,3,2" layout="3col" description="true" checkout_button="Sign Me Up!" price="full"]` + +For more information please visit [the Add On documentation page for this plugin](https://www.paidmembershipspro.com/add-ons/pmpro-advanced-levels-shortcode/). + +## Installation ## +For detailed installation steps, visit the [documentation](https://www.paidmembershipspro.com/add-ons/pmpro-advanced-levels-shortcode/) page. + +1. Download the current development ZIP file directly: `https://github.com/strangerstudios/pmpro-advanced-levels-shortcode/archive/dev.zip` + +**Please ensure that once installing this version of the plugin to remove `-dev` from the plugin's folder name.** + +## Bugs ## +If you find an issue/bug, let us know by [creating a detailed GitHub issue](https://github.com/strangerstudios/pmpro-advanced-levels-shortcode/issues/new/choose). + +## Support ## +This is a developer's portal for Paid Memberships Pro - Advanced Levels Page Shortcode. We do not offer support on this channel. **Any support related questions should be directed to [our website](https://www.paidmembershipspro.com/add-ons/pmpro-advanced-levels-shortcode/).** + +## Contributing to Paid Memberships Pro - Advanced Levels Page Shortcode ## +We encourage and welcome any contribution to Paid Memberships Pro - Advanced Levels Page Shortcode. Please read the [guidelines for contributing](https://github.com/strangerstudios/pmpro-advanced-levels-shortcode/blob/dev/.github/CONTRIBUTING.md) to this repository. + +There are various **ways to the help development** of Paid Memberships Pro - Advanced Levels Page Shortcode: + +1. Report [bugs/issues](https://github.com/strangerstudios/pmpro-advanced-levels-shortcode/issues/new/choose) on GitHub. +2. Work on any issues by submitting a Pull Request. + +Here are some ways for **non-developers to contribute** to Paid Memberships Pro - Advanced Levels Page Shortcode: + +1. Translate Paid Memberships Pro - Advanced Levels Page Shortcode into your own [language](https://www.paidmembershipspro.com/paid-memberships-pro-in-your-language/). +2. [Purchase a Plus membership](https://paidmembershipspro.com/pricing) to help fund ongoing development and bug fixes. diff --git a/pmpro-advanced-levels-shortcode-banner.jpg b/pmpro-advanced-levels-shortcode-banner.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d3248ea09e6a82dec30132ce430fd8917eed50fc GIT binary patch literal 45021 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 literal 0 HcmV?d00001 diff --git a/pmpro-advanced-levels-shortcode.php b/pmpro-advanced-levels-shortcode.php index 3b627b2..1779fd4 100644 --- a/pmpro-advanced-levels-shortcode.php +++ b/pmpro-advanced-levels-shortcode.php @@ -1,13 +1,13 @@ Date: Fri, 20 Oct 2023 11:41:09 -0400 Subject: [PATCH 06/17] Fix renewal button issue --- templates/levels-compare_table.php | 6 +++--- templates/levels-div.php | 7 +++++-- templates/levels.php | 2 -- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/templates/levels-compare_table.php b/templates/levels-compare_table.php index 975570c..4d7a946 100644 --- a/templates/levels-compare_table.php +++ b/templates/levels-compare_table.php @@ -148,7 +148,7 @@ @@ -214,7 +214,7 @@ ID, $level->id); - if(!pmpro_isLevelRecurring( $specific_level ) && !empty( $specific_level->enddate ) ) + if( pmpro_isLevelExpiringSoon( $specific_level ) && $level->allow_signups ) { ?> - - id, $layout); ?> - - id, $layout); ?> + + + - \ No newline at end of file + diff --git a/templates/levels-table.php b/templates/levels-table.php index 5efa6c9..586d291 100644 --- a/templates/levels-table.php +++ b/templates/levels-table.php @@ -4,121 +4,98 @@ */ global $pmproal_link_arguments; + +// Build the selectors for the levels wrapper. +$wrapper_classes = array(); +$wrapper_classes[] = 'pmpro_advanced_levels-table'; +$wrapper_class = implode( ' ', array_unique( $wrapper_classes ) ); ?> -"> - - - - - - - - - - - - - - - -id; - $current_level = pmpro_hasMembershipLevel( $level->id ); +
 
+ + + + + + + + + + + + + + + + id; + $current_level = pmpro_hasMembershipLevel( $level->id ); - ?> - - id, $template); ?> - - - - - + + id, $template); ?> + + id ) ) ) { + $price_text = pmpro_getCustomLevelCostText( $level->id ); + } else { + $price_text = __( 'Free', 'pmpro-advanced-levels-shortcode' ); + } + } elseif ( $price === 'full' ) { + $price_text = pmpro_getLevelCost( $level, true, false ); + } else { + $price_text = pmpro_getLevelCost( $level, false, true ); + } + + $price_classes = array(); + $price_classes[] = 'pmpro_level-price'; + if ( pmpro_isLevelFree ( $level ) ) { + $price_classes[] = 'pmpro_level-price-free'; + } + $price_class = implode( ' ', array_unique( $price_classes ) ); + ?> + + + + + + + - - - id, $template); ?> - - - + id, $template); ?> + + +
 
-

name, pmproal_allowed_html() ); ?>

- description) ); } ?> -
- array() ) ); - else - echo wp_kses( pmpro_getLevelCost( $level, false, true ), array( 'strong' => array() ) ); + // Build the selectors for the single level elements. + $element_classes = array(); + $element_classes[] = 'pmpro_level'; + if ( $highlight == $level->id ) { + $element_classes[] = 'pmpro_level-highlight'; + } + if ( $current_level ) { + $element_classes[] = 'pmpro_level-current'; + } + $element_class = implode( ' ', array_unique( $element_classes ) ); ?> -
+

name, pmproal_allowed_html() ); ?>

+ description ) ) { ?> +
+ description) ); ?> +
+ +
+ + + + - + - - " href=""> - - " href=""> - - - ID, $level->id); - if( pmpro_isLevelExpiringSoon( $specific_level) && $level->allow_signups ) - { - ?> - " href=""> - - " href=""> - - - -
From dce40f0d27a7a47c5e18636c54d091946441bd4e Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Wed, 10 Jan 2024 13:36:53 -0500 Subject: [PATCH 12/17] Removing var dump --- templates/levels-div.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/templates/levels-div.php b/templates/levels-div.php index f0dd03c..3400f0b 100644 --- a/templates/levels-div.php +++ b/templates/levels-div.php @@ -114,8 +114,7 @@

- +

description ) ) { ?> From c03540910b97dd60ddd9d727371fdf68ae69f718 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Fri, 12 Jan 2024 07:52:54 -0500 Subject: [PATCH 13/17] Continued revamp and streamlining code --- css/pmpro-advanced-levels.css | 292 ++++++++------ pmpro-advanced-levels-shortcode.php | 61 ++- templates/levels-compare_table.php | 594 ++++++++-------------------- templates/levels-div.php | 63 +-- templates/levels-table.php | 36 +- templates/levels.php | 276 ++++++------- 6 files changed, 525 insertions(+), 797 deletions(-) diff --git a/css/pmpro-advanced-levels.css b/css/pmpro-advanced-levels.css index de34fcb..8dd434d 100755 --- a/css/pmpro-advanced-levels.css +++ b/css/pmpro-advanced-levels.css @@ -2,6 +2,8 @@ * Root variables */ :root { + --pmproal--border--color: #D1D1D1; + --pmproal--row--color-alt: #0000000D; --pmproal--spacing--large: 50px; --pmproal--spacing--medium: 30px; --pmproal--spacing--small: 10px; @@ -12,6 +14,11 @@ padding: 0; } +.pmpro_level h2 { + margin: 0; + padding: 0; +} + .pmpro_level-description p:not(.pmpro_level-description p:last-of-type) { margin-bottom: var(--pmproal--spacing--small); } @@ -20,9 +27,137 @@ font-weight: bold; } +/** Table Styles */ +.pmpro_advanced_levels-table { + border-collapse: collapse; + margin-bottom: var(--pmproal--spacing--large); +} + +.pmpro_advanced_levels-table th, +.pmpro_advanced_levels-table td { + padding: var(--pmproal--spacing--small); + vertical-align: top; +} + +.pmpro_advanced_levels-table tbody th, +.pmpro_advanced_levels-table tbody td { + padding-top: calc( var(--pmproal--spacing--medium) / 2 ); + padding-bottom: calc( var(--pmproal--spacing--medium) / 2 ); +} + +.pmpro_advanced_levels-table thead th, +.pmpro_advanced_levels-table tbody th { + text-align: left; +} + +.pmpro_advanced_levels-table .pmpro_btn { + min-width: 5em; +} + +/** Div and Column Styles */ +.pmpro_advanced_levels-div { + display: flex; + flex-wrap: wrap; + margin-bottom: var(--pmproal--spacing--large); +} + +.pmpro_advanced_levels-div .pmpro_level { + box-sizing: border-box; + display: flex; + flex-direction: column; + gap: var(--pmproal--spacing--medium); + padding: var(--pmproal--spacing--medium); + width: 100%; +} + +/* No Column (Div) Layout */ +.pmpro_advanced_levels-div .pmpro_level-meta p { + display: inline; +} + +/* 2 Column Layout */ +.pmpro_levels-2col .pmpro_level { + flex: 0 0 50%; +} + +/* 3 Column Layout */ +.pmpro_levels-3col .pmpro_level { + flex: 0 0 33.3333%; + text-align: center; +} + +.pmpro_levels-3col .pmpro_level-description, +.pmpro_levels-3col .pmpro_level ul { + text-align: left; +} + +.pmpro_levels-3col .pmpro_btn { + display: block; +} + +/* 4 Column Layout */ +.pmpro_levels-4col .pmpro_level { + flex: 0 0 25%; + text-align: center; +} + +.pmpro_levels-3col .pmpro_level-description, +.pmpro_levels-4col .pmpro_level ul { + text-align: left; +} + +.pmpro_levels-4col .pmpro_btn { + display: block; + text-wrap: normal; +} + + +/* Column Layout Responsive Styles */ +@media only screen and (min-width: 1161px) { + .pmpro_advanced_levels-div .pmpro_level-meta .pmpro_btn { + float: right; + margin-left: var(--pmproal--spacing--medium); + } +} + +@media only screen and (min-width: 960px) and (max-width: 1160px) { + .pmpro_levels-4col .pmpro_level { + flex: 0 0 33.3333%; + } + .pmpro_advanced_levels-div .pmpro_level-meta .pmpro_btn { + float: right; + margin-left: var(--pmproal--spacing--medium); + } +} + +@media only screen and (min-width: 769px) and (max-width: 959px) { + .pmpro_levels-3col .pmpro_level, + .pmpro_levels-4col .pmpro_level { + flex: 0 0 50%; + } + .pmpro_advanced_levels-div .pmpro_level-meta .pmpro_btn { + float: right; + margin-left: var(--pmproal--spacing--medium); + } +} + +@media (max-width: 768px) { + .pmpro_advanced_levels-div .pmpro_level { + flex: 0 0 100%; + } + .pmpro_advanced_levels-div .pmpro_level-meta { + display: flex; + flex-direction: column; + gap: var(--pmproal--spacing--medium); + } +} + /** Compare Table Styles */ .pmpro_advanced_levels-compare_table { - border: none; + border-collapse: collapse; + margin-bottom: var(--pmproal--spacing--large); + table-layout: fixed; + width: 100%; } #pmpro_levels.pmpro_advanced_levels-table h2 { margin: 0; @@ -43,9 +178,9 @@ .pmpro_advanced_levels-compare_table th, .pmpro_advanced_levels-compare_table td { - border-color: #d1d1d1; + border-color: var(--pmproal--border--color); border-width: 0 1px 1px 0; - padding: 0.75em 1em; + padding: calc( var(--pmproal--spacing--medium) / 2 ); vertical-align: middle; } @@ -65,23 +200,21 @@ .pmpro_advanced_levels-compare_table thead tr th:nth-child(even), .pmpro_advanced_levels-compare_table tbody tr td:nth-child(even) { - background: rgba(0, 0, 0, 0.02); + background-color: var(--pmproal--row--color-alt); } .pmpro_advanced_levels-compare_table thead tr th:first-child, .pmpro_advanced_levels-compare_table tfoot tr td:first-child { - background: none; - text-indent: -9999em; - width: 20%; + background-color: none; } .pmpro_advanced_levels-compare_table thead tr:last-child th, .pmpro_advanced_levels-compare_table tbody tr:last-child td { - border-bottom: 0.5rem solid #ccc; + border-bottom: calc( var(--pmproal--spacing--small) / 2 ) solid var(--pmproal--border--color); } .pmpro_advanced_levels-compare_table tbody tr:nth-child(even) td { - background: rgba(0, 0, 0, 0.05); + background-color: var(--pmproal--row--color-alt); } .pmpro_advanced_levels-compare_table tbody tr td:first-child { @@ -93,13 +226,15 @@ } .pmpro_advanced_levels-compare_table tfoot td { - padding: 0.75em 1em; + padding: calc( var(--pmproal--spacing--medium) / 2 ); vertical-align: middle; } -.pmpro_advanced_levels-compare_table thead th h2 { - margin: 0; - padding: 0.5em 0 0 0; +.pmpro_advanced_levels-compare_table .pmpro_level-description ul { + display: inline-block; + margin-left: var(--pmproal--spacing--medium); + padding-left: 0; + text-align: left; } .pmpro_advanced_levels-compare_table .pmpro_level-price { @@ -124,15 +259,10 @@ content: "\2713"; } -.pmpro_advanced_levels-compare_table .pmpro_level-compare-false, -.pmpro_advanced_levels-compare_table_responsive .pmpro_level-compare-false { - color: rgba(0, 0, 0, 0.2); -} - .pmpro_advanced_levels-compare_table .pmpro_level-compare-false:after, .pmpro_advanced_levels-compare_table_responsive .pmpro_level-compare-false:after { - content: "\002D"; + content: "\2014"; } .pmpro_advanced_levels-compare_table_responsive { @@ -140,6 +270,13 @@ text-align: center; } +.pmpro_advanced_levels-compare_table_responsive ul, +.pmpro_advanced_levels-compare_table_responsive li { + list-style: none; + margin-left: 0; + padding-left: 0; +} + @media only screen and (max-width: 767px) { .pmpro_advanced_levels-compare_table { display: none; @@ -149,119 +286,20 @@ } } -/** Table Styles */ -.pmpro_advanced_levels-table { - margin-bottom: var(--pmproal--spacing--large); -} - -.pmpro_advanced_levels-table th, -.pmpro_advanced_levels-table td { - padding: var(--pmproal--spacing--small); - vertical-align: top; -} - -.pmpro_advanced_levels-table tbody th, -.pmpro_advanced_levels-table tbody td { - padding-top: calc( var(--pmproal--spacing--medium) / 2 ); - padding-bottom: calc( var(--pmproal--spacing--medium) / 2 ); -} - -.pmpro_advanced_levels-table thead th, -.pmpro_advanced_levels-table tbody th { - text-align: left; -} - -.pmpro_advanced_levels-table .pmpro_btn { - min-width: 5em; -} - -/** Div and Column Styles */ -.pmpro_advanced_levels-div { +.pmproal_actions_nav { display: flex; flex-wrap: wrap; - margin-bottom: var(--pmproal--spacing--large); -} - -.pmpro_advanced_levels-div .pmpro_level { - box-sizing: border-box; - display: flex; - flex-direction: column; - gap: var(--pmproal--spacing--medium); - padding: var(--pmproal--spacing--medium); - width: 100%; -} - -.pmpro_advanced_levels-div h2 { - margin: 0; - padding: 0; -} - -/* No Column (Div) Layout */ -.pmpro_advanced_levels-div .pmpro_level-meta { - -} -.pmpro_advanced_levels-div .pmpro_level-meta p { - display: inline; + justify-content: space-between; } -.pmpro_advanced_levels-div .pmpro_level-meta .pmpro_btn { - float: right; - margin-left: var(--pmproal--spacing--medium); -} - -/* 2 Column Layout */ -.pmpro_levels-2col .pmpro_level { - flex: 0 0 50%; -} - -/* 3 Column Layout */ -.pmpro_levels-3col .pmpro_level { - flex: 0 0 33.3333%; - text-align: center; -} - -.pmpro_levels-3col .pmpro_level-description, -.pmpro_levels-3col .pmpro_level ul { - text-align: left; -} - -.pmpro_levels-3col .pmpro_btn { - display: block; -} - -/* 4 Column Layout */ -.pmpro_levels-4col .pmpro_level { - flex: 0 0 25%; - text-align: center; -} - -.pmpro_levels-3col .pmpro_level-description, -.pmpro_levels-4col .pmpro_level ul { +.pmproal_actions_nav .pmpro_actions_nav-left { + flex: 1; + order: 1; text-align: left; } -.pmpro_levels-4col .pmpro_btn { - display: block; - text-wrap: normal; -} - - -/* Column Layout Responsive Styles */ -@media only screen and (min-width: 960px) and (max-width: 1160px) { - .pmpro_levels-4col .pmpro_level { - flex: 0 0 33.3333%; - } -} - -@media only screen and (min-width: 769px) and (max-width: 959px) { - .pmpro_levels-3col .pmpro_level, - .pmpro_levels-4col .pmpro_level { - flex: 0 0 50%; - } -} - -@media (max-width: 768px) { - .pmpro_advanced_levels-div .pmpro_level { - flex: 0 0 100%; +@media only screen and (max-width: 767px) { + .pmproal_actions_nav .pmpro_actions_nav-left { + text-align: center; } -} +} \ No newline at end of file diff --git a/pmpro-advanced-levels-shortcode.php b/pmpro-advanced-levels-shortcode.php index 0f5da2c..c5c978a 100644 --- a/pmpro-advanced-levels-shortcode.php +++ b/pmpro-advanced-levels-shortcode.php @@ -12,9 +12,6 @@ define( 'PMPRO_ADVANCED_LEVELS_DIR', dirname( __FILE__ ) ); -global $pmproal_link_arguments; -$pmproal_link_arguments = array(); - // Include required files. require_once( PMPRO_ADVANCED_LEVELS_DIR . '/templates/levels.php' ); @@ -104,36 +101,79 @@ function pmproal_allowed_html() { return apply_filters( 'pmproal_allowed_html', $allowed_html ); } +/** + * Function to get the level price. + * + * @since TBD + * @param object $level The level object. + * @param string $price The price type from shortcode or block atts. + * @return string $price_text The price text to be displayed. + */ +function pmproal_getLevelPrice( $level, $price ) { + // Build the selectors for the price element. + $price_classes = array(); + $price_classes[] = 'pmpro_level-price'; + + if ( isset( $level->discounted_level ) ) { + $level_to_price = $level->discounted_level; + } else { + $level_to_price = $level; + } + if ( pmpro_isLevelFree ( $level_to_price ) ) { + // Add free class if level is free. + $price_classes[] = 'pmpro_level-price-free'; + + // If pmpro-level-cost-text Add On is installed and activated and the level has a cost text, use that + if ( function_exists( 'pmpro_getCustomLevelCostText' ) && ! empty( pmpro_getCustomLevelCostText( $level_to_price->id ) ) ) { + $price_text = pmpro_getCustomLevelCostText( $level_to_price->id ); + } else { + $price_text = __( 'Free', 'pmpro-advanced-levels-shortcode' ); + } + } elseif ( $price === 'full' ) { + $price_text = pmpro_getLevelCost( $level_to_price, true, false ); + } else { + $price_text = pmpro_getLevelCost( $level_to_price, false, true ); + } + + // Prepare the class selectors for the price element. + $price_class = implode( ' ', array_unique( $price_classes ) ); + ?> +

+ +

+ current_level ) { // Show checkout button if the user has no membership level or $current_level is false $button_classes[] = 'pmpro_btn-select'; - $button_link = add_query_arg( $pmproal_link_arguments, pmpro_url( 'checkout', '', 'https' ) ); + $button_link = add_query_arg( $level->link_arguments, pmpro_url( 'checkout', '', 'https' ) ); $button_text = $checkout_button; - } elseif( $current_level ) { + } elseif( $level->current_level ) { // Get specific level details for the user $specific_level = pmpro_getSpecificMembershipLevelForUser( $current_user->ID, $level->id ); if ( pmpro_isLevelExpiringSoon( $specific_level ) && $specific_level->allow_signups ) { // Show renew button if the level is expiring soon and signups are allowed $button_classes[] = 'pmpro_btn-select'; $button_classes[] = 'pmpro_btn-renew'; - $button_link = add_query_arg( $pmproal_link_arguments, pmpro_url( 'checkout', '', 'https' ) ); + $button_link = add_query_arg( $level->link_arguments, pmpro_url( 'checkout', '', 'https' ) ); $button_text = $renew_button; } else { // Show account button otherwise @@ -149,7 +189,6 @@ function pmproal_level_button( $level, $pmproal_link_arguments, $current_level, id ) { + $element_classes[] = 'pmpro_level-highlight'; + } + if ( $level->current_level ) { + $element_classes[] = 'pmpro_level-current'; + } + $element_class = implode( ' ', array_unique( $element_classes ) ); + $pmpro_levels_filtered[$level->id]->element_class = $element_class; +} + +// Build the selectors for the levels wrapper. +$wrapper_classes = array(); +$wrapper_classes[] = 'pmpro_advanced_levels-compare_table'; +$wrapper_class = implode( ' ', array_unique( $wrapper_classes ) ); ?> -pmpro_advanced_levels-compare_table"> +
- - + - - - - - - + + + - - + + - - - - + + + - - + + - - - - - + + + - - + + - id ); - - $pmproal_link_arguments['level'] = $level->id; - ?> - - + + + - + = 0 && !empty($numeric_levels_array[$count])) + + foreach ( $compareitem_values as $compareitem_value ) { + if ( $count >= 0 && ! empty( $numeric_levels_array[$count] ) ) { $level = $numeric_levels_array[$count]; - else + } else { $level = NULL; + } $count++; ?> - - id; - - $current_level = pmpro_hasMembershipLevel( $level->id ); - ?> - - + + + - + - - - + + + - - - - - - - + + - +
+ foreach ( $pmpro_levels_filtered as $level ) { ?> +

name, pmproal_allowed_html() ); ?>

- - id ) ) ) { - $text = pmpro_getCustomLevelCostText($level->id); - } else { - $text = '' . __( 'Free', 'pmpro-advanced-levels-shortcode' ) . ''; - } - - echo wp_kses( $text, pmproal_allowed_html() ); - - } else if($price === 'full') - echo wp_kses( spanThePMProLevelCostText( pmpro_getLevelCost($level, true, false)), array( 'strong' => array(), 'span' => array() ) ); - else - echo wp_kses( spanThePMProLevelCostText( pmpro_getLevelCost($level, false, true)), array( 'strong' => array(), 'span' => array() ) ); - - ?> + +
+
+
description); ?>
+ +
  - - " href=""> - - " href=""> - - ID, $level->id); - if( pmpro_isLevelExpiringSoon( $specific_level ) && $level->allow_signups ) - { - ?> - " href=""> - - " href=""> - - - + +
- '; - } elseif( $compareitem_value == '0' ) { - echo ''; - } else { echo wp_kses( $compareitem_value, pmproal_allowed_html() ); } + > + ' . esc_html__( 'Yes', 'pmpro-advanced-levels-shortcode' ) . ''; + } elseif ( $compareitem_value == '0' ) { + echo '' . esc_html__( 'No', 'pmpro-advanced-levels-shortcode' ) . ''; + } else { + echo wp_kses( $compareitem_value, pmproal_allowed_html() ); + } ?>
  - - " href=""> - - " href=""> - - ID, $level->id); - if( pmpro_isLevelExpiringSoon( $specific_level ) && $level->allow_signups ) - { - ?> - " href=""> - - " href=""> - - - + +
- - -
id); - } else { - $level_page = null; - - } - - if(!empty($level_page)) - { - ?> - - -
+ +
pmpro_advanced_levels-compare_table_responsive"> -id; - - $count++; - $current_level = pmpro_hasMembershipLevel( $level->id ); + foreach ( $pmpro_levels_filtered as $level ) { + // Build the selectors for the single level elements. + $element_classes = array(); + $element_classes[] = 'pmpro_level'; + if ( $highlight == $level->id ) { + $element_classes[] = 'pmpro_level-highlight'; + } + if ( $level->current_level ) { + $element_classes[] = 'pmpro_level-current'; + } + $element_class = implode( ' ', array_unique( $element_classes ) ); ?> -
-
id) { echo "pmpro_level-highlight "; } if($template === "gantry") { echo " well"; } if($template === "bootstrap") { echo " panel panel-default"; } ?>"> - class="entry-header">>name?> - - -
+
+ id, $layout ); ?> + +

name ); ?>

+ + description ) ) { ?> +
+ description) ); ?> +
- -
- -

"> - '; + foreach ( $compareitems as $compareitem ) { + $compareitem_values = explode( ',', $compareitem ); + if ( $count >= 0 && ! empty( $numeric_levels_array[$count] ) ) { + $compare_level = $numeric_levels_array[$count]; + } else { + $compare_level = NULL; } - ?> - id ) ) ) { - $text = pmpro_getCustomLevelCostText( $level->id ); - } else { - $text = '' . __( 'Free', 'pmpro-advanced-levels-shortcode' ) . ''; - } - - echo wp_kses( $text , pmproal_allowed_html() ); - } elseif($price === 'full') { - echo wp_kses( pmpro_getLevelCost( $level, true, false ), pmproal_allowed_html() ); + if ( $compareitem_values[$count] != '0' ) { + if ( $compareitem_values[$count] == '1' ) { + echo '' . wp_kses( $compareitem_values[0], pmproal_allowed_html() ) . ''; } else { - echo wp_kses( pmpro_getLevelCost( $level, false, true ), pmproal_allowed_html() ); + echo '' . wp_kses( $compareitem_values[0], pmproal_allowed_html() ) . ': '; + echo wp_kses( $compareitem_values[$count], pmproal_allowed_html() ); } - - if($template === "foundation") - { - ?> -

- -

- '; } - ?> - - description)) { ?> - class="entry-content"> - description) ); ?> -
- - '; - foreach($compareitems as $compareitem) - { - $compareitem_values = explode(",", $compareitem); - if($count >= 0 && !empty($numeric_levels_array[$count])) - $compare_level = $numeric_levels_array[$count]; - else - $compare_level = NULL; - if($compareitem_values[$count] != '0') - { - if($compareitem_values[$count] == '1') - { - echo ' ' . wp_kses( $compareitem_values[0], pmproal_allowed_html() ) . ''; - } - else - { - echo ' ' . wp_kses( $compareitem_values[0], pmproal_allowed_html() ) . ': '; - echo wp_kses( $compareitem_values[$count], pmproal_allowed_html() ); - } - echo '
'; - } - } - echo '

'; - } - ?> - class="entry-footer"> - -
- -
+ echo '

'; + } ?> + +
+ + + + + + +

+ +

+ + +
+ id, $layout ); ?> +
diff --git a/templates/levels-div.php b/templates/levels-div.php index 3400f0b..03f91f9 100644 --- a/templates/levels-div.php +++ b/templates/levels-div.php @@ -2,7 +2,6 @@ /* Template for layout= "div" or "2col" or "3col" or "4col" */ -global $pmproal_link_arguments; // Build the selectors for the levels div wrapper. $wrapper_classes = array(); @@ -15,16 +14,13 @@
id; - $current_level = pmpro_hasMembershipLevel( $level->id ); - // Build the selectors for the single level elements. $element_classes = array(); $element_classes[] = 'pmpro_level'; if ( $highlight == $level->id ) { $element_classes[] = 'pmpro_level-highlight'; } - if ( $current_level ) { + if ( $level->current_level ) { $element_classes[] = 'pmpro_level-current'; } $element_class = implode( ' ', array_unique( $element_classes ) ); @@ -43,33 +39,9 @@
- + - id ) ) ) { - $price_text = pmpro_getCustomLevelCostText( $level->id ); - } else { - $price_text = __( 'Free', 'pmpro-advanced-levels-shortcode' ); - } - } elseif ( $price === 'full' ) { - $price_text = pmpro_getLevelCost( $level, true, false ); - } else { - $price_text = pmpro_getLevelCost( $level, false, true ); - } - - $price_classes = array(); - $price_classes[] = 'pmpro_level-price'; - if ( pmpro_isLevelFree ( $level ) ) { - $price_classes[] = 'pmpro_level-price-free'; - } - $price_class = implode( ' ', array_unique( $price_classes ) ); - ?> -

- -

- + @@ -83,38 +55,13 @@
- id ) ) ) { - $price_text = pmpro_getCustomLevelCostText( $level->id ); - } else { - $price_text = __( 'Free', 'pmpro-advanced-levels-shortcode' ); - } - } elseif ( $price === 'full' ) { - $price_text = pmpro_getLevelCost( $level, true, false ); - } else { - $price_text = pmpro_getLevelCost( $level, false, true ); - } - - $price_classes = array(); - $price_classes[] = 'pmpro_level-price'; - if ( pmpro_isLevelFree ( $level ) ) { - $price_classes[] = 'pmpro_level-price-free'; - } - $price_class = implode( ' ', array_unique( $price_classes ) ); - ?> -

- -

- + pmproal_getLevelPrice( $level, $price ); ?>

- +

description ) ) { ?> diff --git a/templates/levels-table.php b/templates/levels-table.php index 586d291..2278182 100644 --- a/templates/levels-table.php +++ b/templates/levels-table.php @@ -3,7 +3,6 @@ template for layout="table" */ -global $pmproal_link_arguments; // Build the selectors for the levels wrapper. $wrapper_classes = array(); @@ -28,16 +27,13 @@ id; - $current_level = pmpro_hasMembershipLevel( $level->id ); - // Build the selectors for the single level elements. $element_classes = array(); $element_classes[] = 'pmpro_level'; if ( $highlight == $level->id ) { $element_classes[] = 'pmpro_level-highlight'; } - if ( $current_level ) { + if ( $level->current_level ) { $element_classes[] = 'pmpro_level-current'; } $element_class = implode( ' ', array_unique( $element_classes ) ); @@ -52,30 +48,10 @@
- id ) ) ) { - $price_text = pmpro_getCustomLevelCostText( $level->id ); - } else { - $price_text = __( 'Free', 'pmpro-advanced-levels-shortcode' ); - } - } elseif ( $price === 'full' ) { - $price_text = pmpro_getLevelCost( $level, true, false ); - } else { - $price_text = pmpro_getLevelCost( $level, false, true ); - } - - $price_classes = array(); - $price_classes[] = 'pmpro_level-price'; - if ( pmpro_isLevelFree ( $level ) ) { - $price_classes[] = 'pmpro_level-price-free'; - } - $price_class = implode( ' ', array_unique( $price_classes ) ); - ?> - - - + + + + - + id, $template); ?> diff --git a/templates/levels.php b/templates/levels.php index e60eac6..2c403e4 100644 --- a/templates/levels.php +++ b/templates/levels.php @@ -1,12 +1,8 @@ id == $level_id && true == $level->allow_signups) - { - $pmpro_levels_filtered[$level->id] = $level; - break; - } + $levels_order = explode(",", $levels); + //loop through $levels_order array and pull levels from $levels + foreach($levels_order as $level_id) { + foreach($pmpro_all_levels as $level) { + if($level->id == $level_id && true == $level->allow_signups) { + $pmpro_levels_filtered[$level->id] = $level; + break; } } - } else { - $pmpro_level_order = get_option( 'pmpro_level_order' ) ?: $pmpro_all_levels; + } + } else { + $pmpro_level_order = get_option( 'pmpro_level_order' ) ?: $pmpro_all_levels; - if ( ! is_array( $pmpro_level_order ) ) { - $levels_order = explode( ',', $pmpro_level_order ); - } else { - $levels_order = array_keys( $pmpro_level_order ); - } + if ( ! is_array( $pmpro_level_order ) ) { + $levels_order = explode( ',', $pmpro_level_order ); + } else { + $levels_order = array_keys( $pmpro_level_order ); + } - // Reorder array - foreach ( $levels_order as $level_id ) { - foreach ( $pmpro_all_levels as $key => $level ) { - if ( $level_id == $level->id ) { - $pmpro_levels_filtered[] = $pmpro_all_levels[$key]; - } + // Reorder array + foreach ( $levels_order as $level_id ) { + foreach ( $pmpro_all_levels as $key => $level ) { + if ( $level_id == $level->id ) { + $pmpro_levels_filtered[] = $pmpro_all_levels[$key]; } } } + } - // Check if we have any level IDs that aren't shown and set a message for admins. - $pmpro_levels_filtered_not_shown = array_diff( $levels_order, array_keys( $pmpro_levels_filtered ) ); - if ( ! empty( $pmpro_levels_filtered_not_shown ) && current_user_can( 'manage_options' ) ) { - // Make sure no level IDs are duplicated. - $pmpro_levels_filtered_not_shown = array_unique( $pmpro_levels_filtered_not_shown ); - - // Create a message to display to admins. - pmpro_setMessage( - sprintf( - __( 'Admin-only message: The following level IDs are not shown because they do not exist or signup is disabled: %s', 'pmpro-advanced-levels-shortcode' ), - implode( ', ', $pmpro_levels_filtered_not_shown ) - ), - 'pmpro_error' - ); - } + // Check if we have any level IDs that aren't shown and set a message for admins. + $pmpro_levels_filtered_not_shown = array_diff( $levels_order, array_keys( $pmpro_levels_filtered ) ); + if ( ! empty( $pmpro_levels_filtered_not_shown ) && current_user_can( 'manage_options' ) ) { + // Make sure no level IDs are duplicated. + $pmpro_levels_filtered_not_shown = array_unique( $pmpro_levels_filtered_not_shown ); - $pmpro_levels_filtered = apply_filters("pmpro_levels_array", $pmpro_levels_filtered); - $numeric_levels_array = array_values($pmpro_levels_filtered); - - //update per discount code - if(!empty($discount_code) && !empty($pmpro_levels_filtered)) { - foreach($pmpro_levels_filtered as $level_id => $level) - { - //check code for this level and update if applicable - if(pmpro_checkDiscountCode($discount_code, $level->id)) - { - $pmproal_link_arguments['discount_code'] = $discount_code; - - $sqlQuery = "SELECT l.id, cl.*, l.name, l.description, l.allow_signups FROM $wpdb->pmpro_discount_codes_levels cl LEFT JOIN $wpdb->pmpro_membership_levels l ON cl.level_id = l.id LEFT JOIN $wpdb->pmpro_discount_codes dc ON dc.id = cl.code_id WHERE dc.code = '" . $discount_code . "' AND cl.level_id = '" . (int)$level->id . "' LIMIT 1"; - $pmpro_levels_filtered[$level_id] = $wpdb->get_row($sqlQuery); - $pmpro_levels_filtered[$level_id]->base_level = $level; - - } - } - } else { - unset( $pmproal_link_arguments['discount_code'] ); - } + // Create a message to display to admins. + pmpro_setMessage( + sprintf( + __( 'Admin-only message: The following level IDs are not shown because they do not exist or signup is disabled: %s', 'pmpro-advanced-levels-shortcode' ), + implode( ', ', $pmpro_levels_filtered_not_shown ) + ), + 'pmpro_error' + ); + } - // Show the pmpro_msg variable. - if ( $pmpro_msg ) { ?> -
- discounted_level = null; + $level->current_level = false; + + // Set the level ID in the link arguments. + $level->link_arguments = array(); + $level->link_arguments['level'] = $level->id; + + // Check the discount code for this level and update the link arguments if applicable. + if ( ! empty( $discount_code ) && pmpro_checkDiscountCode( $discount_code, $level->id ) ) { + $level->link_arguments['discount_code'] = $discount_code; + $level->discounted_level = pmpro_getLevelAtCheckout( $level->id, $discount_code ); } - else - { - //load template for layout = "div", "2col", "3col", "4col" or unspecified layout attribute - include("levels-div.php"); - } - ?> - '; } ?> - - - '; } ?> - + + + + $1", $text); - - //return - return $level_cost; -} +add_shortcode( 'pmpro_advanced_levels', 'pmpro_advanced_levels_shortcode' ); From 6d851f036f87e38119f72b01214f9c588a368bf5 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Wed, 17 Jan 2024 16:01:43 -0500 Subject: [PATCH 14/17] CSS fix --- css/pmpro-advanced-levels.css | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/css/pmpro-advanced-levels.css b/css/pmpro-advanced-levels.css index 8dd434d..f08daaa 100755 --- a/css/pmpro-advanced-levels.css +++ b/css/pmpro-advanced-levels.css @@ -3,12 +3,16 @@ */ :root { --pmproal--border--color: #D1D1D1; - --pmproal--row--color-alt: #0000000D; + --pmproal--row--color-alt: #00000008; --pmproal--spacing--large: 50px; --pmproal--spacing--medium: 30px; --pmproal--spacing--small: 10px; } +.wp-block-pmpro-advanced-levels-advanced-levels-page { + overflow: visible; +} + .pmpro_level p { margin: 0; padding: 0; @@ -51,6 +55,7 @@ } .pmpro_advanced_levels-table .pmpro_btn { + display: block; min-width: 5em; } @@ -66,7 +71,7 @@ display: flex; flex-direction: column; gap: var(--pmproal--spacing--medium); - padding: var(--pmproal--spacing--medium); + padding: calc( var(--pmproal--spacing--medium) / 2 ); width: 100%; } @@ -179,23 +184,20 @@ .pmpro_advanced_levels-compare_table th, .pmpro_advanced_levels-compare_table td { border-color: var(--pmproal--border--color); - border-width: 0 1px 1px 0; + border-style: solid; + border-width: 0 1px 0 0; padding: calc( var(--pmproal--spacing--medium) / 2 ); vertical-align: middle; } -.pmpro_advanced_levels-compare_table thead th, -.pmpro_advanced_levels-compare_table tfoot td { - border-width: 0 1px 0 0; -} - -.pmpro_advanced_levels-compare_table thead tr { - border: none; +.pmpro_advanced_levels-compare_table thead tr:first-child th:not(.pmpro_advanced_levels-compare_table thead tr:first-child th:first-child) { + border-top-width: 1px; + padding-top: var(--pmproal--spacing--medium); } .pmpro_advanced_levels-compare_table tr th:last-child, .pmpro_advanced_levels-compare_table tr td:last-child { - border-right: none; + border-right-width: 1px; } .pmpro_advanced_levels-compare_table thead tr th:nth-child(even), @@ -215,21 +217,23 @@ .pmpro_advanced_levels-compare_table tbody tr:nth-child(even) td { background-color: var(--pmproal--row--color-alt); + border-top-width: 1px; } .pmpro_advanced_levels-compare_table tbody tr td:first-child { text-align: right; } -.pmpro_advanced_levels-compare_table tfoot tr { - border: none; -} - .pmpro_advanced_levels-compare_table tfoot td { padding: calc( var(--pmproal--spacing--medium) / 2 ); vertical-align: middle; } +.pmpro_advanced_levels-compare_table tfoot tr:last-child td:not(.pmpro_advanced_levels-compare_table tfoot tr:last-child td:first-child) { + border-bottom-width: 1px; +} + + .pmpro_advanced_levels-compare_table .pmpro_level-description ul { display: inline-block; margin-left: var(--pmproal--spacing--medium); From 8c24b4999540e6824fe5c845892f683e85b5581a Mon Sep 17 00:00:00 2001 From: Andrew Lima Date: Fri, 19 Jan 2024 12:48:16 +0200 Subject: [PATCH 15/17] Fix admin only message * BUG FIX: Fixed an issue where the admin only message would display if you had a space between your levels attribute value or no value at all. Fixed an issue where no levels attribute would cause the warning to display as well. --- templates/levels.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/templates/levels.php b/templates/levels.php index 2c403e4..477bf1e 100644 --- a/templates/levels.php +++ b/templates/levels.php @@ -81,7 +81,11 @@ function pmpro_advanced_levels_shortcode($atts, $content=null, $code="") { : implode( ',', wp_list_pluck( $levels, 'value' ) ); } - $levels_order = explode(",", $levels); + // Clean up the $levels_order to prevent false positives and ensure data integrity. + $levels_order = explode( ',', $levels ); + $levels_order = array_map( 'trim', $levels_order ); + $levels_order = array_filter( $levels_order ); + //loop through $levels_order array and pull levels from $levels foreach($levels_order as $level_id) { foreach($pmpro_all_levels as $level) { @@ -111,7 +115,7 @@ function pmpro_advanced_levels_shortcode($atts, $content=null, $code="") { } // Check if we have any level IDs that aren't shown and set a message for admins. - $pmpro_levels_filtered_not_shown = array_diff( $levels_order, array_keys( $pmpro_levels_filtered ) ); + $pmpro_levels_filtered_not_shown = array_diff( $levels_order, wp_list_pluck( $pmpro_levels_filtered, 'id' ) ); if ( ! empty( $pmpro_levels_filtered_not_shown ) && current_user_can( 'manage_options' ) ) { // Make sure no level IDs are duplicated. $pmpro_levels_filtered_not_shown = array_unique( $pmpro_levels_filtered_not_shown ); @@ -119,7 +123,7 @@ function pmpro_advanced_levels_shortcode($atts, $content=null, $code="") { // Create a message to display to admins. pmpro_setMessage( sprintf( - __( 'Admin-only message: The following level IDs are not shown because they do not exist or signup is disabled: %s', 'pmpro-advanced-levels-shortcode' ), + esc_html__( 'Admin-only message: The following level IDs are not shown because they do not exist or signup is disabled: %s', 'pmpro-advanced-levels-shortcode' ), implode( ', ', $pmpro_levels_filtered_not_shown ) ), 'pmpro_error' From d647581222679d42054e0b6d934fd60ffb8ff7a3 Mon Sep 17 00:00:00 2001 From: Andrew Lima Date: Fri, 19 Jan 2024 13:19:03 +0200 Subject: [PATCH 16/17] Fix hide price * BUG FIX: Fixed an issue where the hide price wasn't working on the DIV template. --- templates/levels-div.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/levels-div.php b/templates/levels-div.php index 03f91f9..49f4931 100644 --- a/templates/levels-div.php +++ b/templates/levels-div.php @@ -41,7 +41,7 @@ - + @@ -58,7 +58,7 @@ + if ( ! empty( $show_price ) ) { pmproal_getLevelPrice( $level, $price ); } ?>

From 8c7c731552339313f0d726955a7cadfdc3bfd6d4 Mon Sep 17 00:00:00 2001 From: Andrew Lima Date: Fri, 19 Jan 2024 15:23:45 +0200 Subject: [PATCH 17/17] V1.0 Bump --- pmpro-advanced-levels-shortcode.php | 12 ++++++------ readme.txt | 10 ++++++++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/pmpro-advanced-levels-shortcode.php b/pmpro-advanced-levels-shortcode.php index c5c978a..8124fb0 100644 --- a/pmpro-advanced-levels-shortcode.php +++ b/pmpro-advanced-levels-shortcode.php @@ -3,7 +3,7 @@ Plugin Name: Paid Memberships Pro - Advanced Levels Page Shortcode Add On Plugin URI: https://www.paidmembershipspro.com/add-ons/pmpro-advanced-levels-shortcode/ Description: An enhanced shortcode for customizing the display of your Membership Levels Page for Paid Memberships Pro -Version: 0.2.6 +Version: 1.0 Author: Paid Memberships Pro Author URI: https://www.paidmembershipspro.com/ Text Domain: pmpro-advanced-levels-shortcode @@ -68,7 +68,7 @@ function pmproal_getLevelLandingPage($level_id) { /** * Function for allowed HTML tags in various templates * - * @since TBD + * @since 1.0 * @return array $allowed_html The allowed HTML to be used for wp_kses escaping. */ function pmproal_allowed_html() { @@ -96,7 +96,7 @@ function pmproal_allowed_html() { /** * Filters the allowed HTML tags for the Advanced Levels Shortcode. * @param array $allowed_html The allowed html elements for the Advanced Levels Shortcode escaping where wp_kses is used (like in compared elements etc.) - * @since TBD + * @since 1.0 */ return apply_filters( 'pmproal_allowed_html', $allowed_html ); } @@ -104,7 +104,7 @@ function pmproal_allowed_html() { /** * Function to get the level price. * - * @since TBD + * @since 1.0 * @param object $level The level object. * @param string $price The price type from shortcode or block atts. * @return string $price_text The price text to be displayed. @@ -147,7 +147,7 @@ function pmproal_getLevelPrice( $level, $price ) { /** * Function to get the level button. * - * @since TBD + * @since 1.0 * @param object $level The level object. * @param string $checkout_button The text for the checkout button from shortcode or block atts. * @param string $renew_button The text for the renew button from shortcode or block atts. @@ -192,7 +192,7 @@ function pmproal_level_button( $level, $checkout_button, $renew_button, $account /** * Register block types for the block editor. * - * @since TBD + * @since 1.0 */ function pmpro_advanced_levels_register_block_types() { register_block_type( __DIR__ . '/blocks/build/advanced-levels-page' ); diff --git a/readme.txt b/readme.txt index 6b29623..b5ff5f5 100644 --- a/readme.txt +++ b/readme.txt @@ -2,8 +2,8 @@ Contributors: strangerstudios Tags: pmpro, paid memberships pro, members, memberships, levels, templates, pricing, columns, themes Requires at least: 5.4 -Tested up to: 6.4 -Stable tag: 0.2.6 +Tested up to: 6.4.2 +Stable tag: 1.0 An enhanced shortcode for customizing the display of your Membership Levels Page for Paid Memberships Pro. @@ -32,6 +32,12 @@ For more information about shortcode attributes, see the documentation here: https://www.paidmembershipspro.com/add-ons/pmpro-advanced-levels-shortcode/#h-shortcode-example-and-attributes == Changelog == += 1.0 - 2024-01-19 = +* ENHANCEMENT: Added warnings to admins when adding a non-existent or disabled level to the shortcode levels attribute. +* REFACTOR: Reworked how blocks are structured within the plugin to follow the latest coding practice. +* REFACTOR: General code cleanup and improvements. +* BUG FIX: Fixed an issue where the "Renew" button on the level page would not show correctly. +* BUG FIX: Fixed an issue where the "hide" price attribute wasn't working with the DIV layout. = 0.2.6 - 2023-08-29 = * ENHANCEMENT: Improved support for the Custom Level Cost Text Add On and free levels. (@MaximilianoRicoTabo, @andrewlimaza)