From 178166650002055e5aa05347eeb7e558abea0312 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 3 Nov 2024 17:36:12 -0500 Subject: [PATCH 01/24] Initial basic styling to match PMPro v3.1 --- css/pmpro-member-directory.css | 86 ++- templates/directory.php | 936 +++++++++++++++++---------------- templates/profile.php | 452 ++++++++-------- 3 files changed, 775 insertions(+), 699 deletions(-) diff --git a/css/pmpro-member-directory.css b/css/pmpro-member-directory.css index 296c18b..58c314c 100644 --- a/css/pmpro-member-directory.css +++ b/css/pmpro-member-directory.css @@ -1,9 +1,15 @@ /* CSS Document */ +form.pmpro_member_directory_search { + align-items: center; + display: flex; + flex-direction: row; + gap: var(--pmpro--base--spacing--small); + justify-content: flex-end; -h2#pmpro_member_directory_subheading {clear: none; margin-top: 0; } -form.pmpro_member_directory_search {float: right; margin-bottom: 1rem; clear: both; } -form.pmpro_member_directory_search input[type=text] { } -form.pmpro_member_directory_search input[type=submit] {background: none; border: none; padding: 0; position: absolute; text-indent: -9999em; } + .pmpro_form_submit { + margin: 0; + } +} .pmpro_member_directory {clear: both; } .pmpro_pagination {margin: 1em 0;} @@ -24,51 +30,87 @@ div.pmpro_member_profile strong {display: block; } .pmpro_member_directory.pmpro_member_directory-2col, .pmpro_member_directory.pmpro_member_directory-3col, .pmpro_member_directory.pmpro_member_directory-4col { - display: grid; - grid-column-gap: 2.9rem; - grid-row-gap: 5.8rem; - text-align: center; + display: grid; + grid-column-gap: 2.9rem; + grid-row-gap: 2.9rem; + + .pmpro_card { + margin: 0; + + .pmpro_card_title a { + text-decoration: none; + } + .pmpro_card_title a:hover { + text-decoration: underline; + } + + .pmpro_card_title.pmpro_heading-avatar-right { + flex-direction: row-reverse; + justify-content: space-between; + } + .pmpro_card_title.pmpro_heading-avatar-top { + align-items: flex-start; + flex-direction: column; + } + .pmpro_card_content { + display: flex; + flex-direction: column; + gap: var(--pmpro--base--spacing--small); + } + + .pmpro_card_actions { + margin-top: auto; + } + } } .pmpro_member_directory.pmpro_member_directory-2col { - grid-template-columns: 1fr 1fr; + grid-template-columns: 1fr 1fr; } .pmpro_member_directory.pmpro_member_directory-3col { - grid-template-columns: 1fr 1fr 1fr; + grid-template-columns: 1fr 1fr 1fr; } .pmpro_member_directory.pmpro_member_directory-4col { - grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-columns: 1fr 1fr 1fr 1fr; } /* single directory item in list */ .pmpro_member_directory .pmpro_member_directory-item, .pmpro_member_directory .pmpro_member_directory_row { - word-break: break-word; + word-break: break-word; } .pmpro_member_directory_link { - word-break: normal; + word-break: normal; } /* single profile item */ -.pmpro_member_profile { } +.pmpro_member_profile { + + .pmpro_card_content { + display: flex; + flex-direction: column; + gap: var(--pmpro--base--spacing--medium); + margin-top: var(--pmpro--base--spacing--medium); + } +} .pmpro_member_profile .pmpromd_filename { - display: block; + display: block; } @media only screen and (max-width: 767px) { - .pmpro_member_directory.pmpro_member_directory-2col, - .pmpro_member_directory.pmpro_member_directory-3col, - .pmpro_member_directory.pmpro_member_directory-4col { - grid-template-columns: 1fr; - } + .pmpro_member_directory.pmpro_member_directory-2col, + .pmpro_member_directory.pmpro_member_directory-3col, + .pmpro_member_directory.pmpro_member_directory-4col { + grid-template-columns: 1fr; + } } /** * Pagination/page numbers */ .pmpro_page_numbers a { - padding: 6px; + padding: 6px; } .pmpro_page_numbers a.pmpro_page_active { - font-weight: bold; + font-weight: bold; } \ No newline at end of file diff --git a/templates/directory.php b/templates/directory.php index e51191d..f90c4df 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -10,7 +10,7 @@ function pmpromd_shortcode($atts, $content=null, $code="") // examples: [pmpro_member_directory show_avatar="false" show_email="false" levels="1,2"] extract(shortcode_atts(array( - 'avatar_size' => '128', + 'avatar_size' => '64', 'fields' => NULL, 'layout' => 'div', 'level' => NULL, @@ -167,196 +167,394 @@ function pmpromd_shortcode($atts, $content=null, $code="") $user_identifier = pmpromd_user_identifier(); ob_start(); - ?> - - - - -

- - - %s.','pmpro-member-directory'), stripslashes( ucwords(esc_html($s)))); ?> - - - - 0) { ?> - - () - +
+ + -

- "> + + + %s.','pmpro-member-directory'), stripslashes( ucwords(esc_html($s)))); ?> + + + + 0) { ?> + + () + + + + + options)) - $rh_fields[$field->name] = $field->options; + else + $fields_array = false; + + + /** + * Allow filtering the fields to include on the member directory list. + * + * @since TBD + * + * @param array $fields_array The list of fields to include. + */ + $fields_array = apply_filters( 'pmpro_member_directory_fields', $fields_array ); + + // Get Register Helper field options + $rh_fields = array(); + if(!empty($pmprorh_registration_fields)) { + foreach($pmprorh_registration_fields as $location) { + foreach($location as $field) { + if(!empty($field->options)) + $rh_fields[$field->name] = $field->options; + } } } - } - ?> + ?> - $avatar_size, - 'fields' => $fields, - 'layout' => $layout, - 'level' => $level, - 'levels' => $levels, - 'limit' => $limit, - 'link' => $link, - 'order_by' => $order_by, - 'order' => $order, - 'show_avatar' => $show_avatar, - 'show_email' => $show_email, - 'show_level' => $show_level, - 'show_search' => $show_search, - 'show_startdate' => $show_startdate, - 'avatar_align' => $avatar_align, - 'fields_array' => $fields_array - ) ); - - do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); ?> - -
+ $avatar_size, + 'fields' => $fields, + 'layout' => $layout, + 'level' => $level, + 'levels' => $levels, + 'limit' => $limit, + 'link' => $link, + 'order_by' => $order_by, + 'order' => $order, + 'show_avatar' => $show_avatar, + 'show_email' => $show_email, + 'show_level' => $show_level, + 'show_search' => $show_search, + 'show_startdate' => $show_startdate, + 'avatar_align' => $avatar_align, + 'fields_array' => $fields_array + ) ); + + do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); ?> - - - - - - - - - - - - - - - - - - - - - - - - +
+ + +
+
+
- - - - - - - - - - - -  
+ + + + + + + + + + + + + + + + + + + + + + + ID); + $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); + $user_fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); + $count++; + ?> + "> + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +  
+ + ID, $avatar_size, NULL, $auser->user_nicename ); ?> + + ID, $avatar_size, NULL, $auser->user_nicename ); ?> + + + + + + + + + + + user_email, 'user_email' ); ?> + + {$field[1]}; + if(!empty($meta_field)) + { + ?> +
+ + + + $value) + $meta_field[$key] = $rh_fields[$field[1]][$value]; + } + ?> + + + + + + + + {$field[1]}, $field[1] ); ?> + +
+ +
+ ID ); + $membership_levels = array(); + if ( ! isset( $levels ) ) { + // Show all the user's levels. + foreach ( $alluserlevels as $curlevel ) { + $membership_levels[] = $curlevel->name; + } + } else { + $levels_array = explode(',', $levels); + // Show only the levels included in the directory. + foreach ( $alluserlevels as $curlevel ) { + if ( in_array( $curlevel->id, $levels_array) ) { + $membership_levels[] = $curlevel->name; + } + } + } + $auser->membership_levels = implode( ', ', $membership_levels ); + echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; + ?> + + startdate < $min_startdate ) { + $min_startdate = $level->startdate; + } + } + echo ! empty( $min_startdate ) ? date_i18n( get_option( 'date_format' ), $min_startdate ) : ''; + ?> +
+
+ ID); + } + else + { + foreach($theusers as $auser): + $auser = get_userdata($auser->ID); $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); + $user_identifier = pmpromd_user_identifier(); $user_fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); - $count++; ?> - "> - - - - ID, $avatar_size, NULL, $auser->user_nicename ); ?> - - ID, $avatar_size, NULL, $auser->user_nicename ); ?> - - - - -

- - +
+ +

+ + + ID, $avatar_size, NULL, $auser->display_name); ?> - + ID, $avatar_size, NULL, $auser->display_name); ?> -

- - - - user_email, 'user_email' ); ?> - - - - - + + + + + +

+
+ +
+ + user_email, 'user_email' ); ?> +
+ + +
+ + ID ); + $membership_levels = array(); + if ( ! isset( $levels ) ) { + // Show all the user's levels. + foreach ( $alluserlevels as $curlevel ) { + $membership_levels[] = $curlevel->name; + } + } else { + $levels_array = explode(',', $levels); + // Show only the levels included in the directory. + foreach ( $alluserlevels as $curlevel ) { + if ( in_array( $curlevel->id, $levels_array) ) { + $membership_levels[] = $curlevel->name; + } + } + } + $auser->membership_levels = implode( ', ', $membership_levels ); + echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; + ?> +
+ + +
+ + membership_level->startdate); ?> +
+ + -

+

- - - + + + + ?> {$field[1]}, $field[1] ); ?> - -

+
- - - - - ID ); - $membership_levels = array(); - if ( ! isset( $levels ) ) { - // Show all the user's levels. - foreach ( $alluserlevels as $curlevel ) { - $membership_levels[] = $curlevel->name; - } - } else { - $levels_array = explode(',', $levels); - // Show only the levels included in the directory. - foreach ( $alluserlevels as $curlevel ) { - if ( in_array( $curlevel->id, $levels_array) ) { - $membership_levels[] = $curlevel->name; - } - } - } - $auser->membership_levels = implode( ', ', $membership_levels ); - echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; - ?> - - - - - startdate < $min_startdate ) { - $min_startdate = $level->startdate; - } } - echo ! empty( $min_startdate ) ? date_i18n( get_option( 'date_format' ), $min_startdate ) : ''; ?> - +
+ +
+ +
- - - - - - - - - - ID); - $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); - $user_identifier = pmpromd_user_identifier(); - $user_fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); - ?> -
- -
- - ID, $avatar_size, NULL, $auser->display_name); ?> - - ID, $avatar_size, NULL, $auser->display_name); ?> - -
- -

- - - - - -

- -

- - user_email, 'user_email' ); ?> -

- - -

- - ID ); - $membership_levels = array(); - if ( ! isset( $levels ) ) { - // Show all the user's levels. - foreach ( $alluserlevels as $curlevel ) { - $membership_levels[] = $curlevel->name; - } - } else { - $levels_array = explode(',', $levels); - // Show only the levels included in the directory. - foreach ( $alluserlevels as $curlevel ) { - if ( in_array( $curlevel->id, $levels_array) ) { - $membership_levels[] = $curlevel->name; - } - } - } - $auser->membership_levels = implode( ', ', $membership_levels ); - echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; - ?> -

- - -

- - membership_level->startdate); ?> -

- - + +
+ {$field[1]}; - if(!empty($meta_field)) - { - ?> -

- - - - $value) - $meta_field[$key] = $rh_fields[$field[1]][$value]; - } - ?> - - - - - - - - {$field[1]}, $field[1] ); ?> - -

- - - - - + do_action( 'pmpro_member_directory_after', $sqlQuery, $shortcode_atts ); + + } + } + else + { + ?> +

+ - - %s.','pmpro-member-directory'), stripslashes( ucwords(esc_html($s))) ); + if(!empty($directory_url)) + { + ?> + + +

+ -

- +

%s.','pmpro-member-directory'), stripslashes( ucwords(esc_html($s))) ); - if(!empty($directory_url)) - { - ?> - - 1 ) { + $query_args = array( + 'ps' => $s, + 'pn' => $pn-1, + 'limit' => $limit, + ); + $query_args = apply_filters( 'pmpromd_pagination_url', $query_args, 'prev' ); + ?> + « + -

- -
- 1 ) { - $query_args = array( - 'ps' => $s, - 'pn' => $pn-1, - 'limit' => $limit, - ); - $query_args = apply_filters( 'pmpromd_pagination_url', $query_args, 'prev' ); + $number_of_pages = $totalrows / $limit; + //Page Numbers ?> - « + - - ID ) ) ) . '" title="' . esc_attr__( 'Previous', 'pmpromd' ) . '">...'; - } + $counter = 0; + if ( empty( $pn ) || $pn != 1 ) { + echo '...'; + } - if( round( $number_of_pages, 0 ) !== 1 && $pn !== 1 ) { - //If there's only one page, no need to show the page numbers - for( $i = $pn; $i <= $number_of_pages; $i++ ){ - if( $counter <= 6 ){ - $query_args = array( - 'ps' => $s, - 'pn' => $i, - 'limit' => $limit, - ); - - if( $i == $pn ){ $active_class = 'class="pmpro_page_active"'; } else { $active_class = ''; } - - echo '' . $i . ''; - } - $counter++; - } - } - ?> - - $end ) { - $query_args = array( - 'ps' => $s, - 'pn' => $pn+1, - 'limit' => $limit, - ); - $query_args = apply_filters( 'pmpromd_pagination_url', $query_args, 'next' ); + if( round( $number_of_pages, 0 ) !== 1 && $pn !== 1 ) { + //If there's only one page, no need to show the page numbers + for( $i = $pn; $i <= $number_of_pages; $i++ ){ + if( $counter <= 6 ){ + $query_args = array( + 'ps' => $s, + 'pn' => $i, + 'limit' => $limit, + ); + + if( $i == $pn ){ $active_class = 'class="pmpro_page_active"'; } else { $active_class = ''; } + + echo '' . $i . ''; + } + $counter++; + } + } ?> - » + -
- + //next + if ( $totalrows > $end ) { + $query_args = array( + 'ps' => $s, + 'pn' => $pn+1, + 'limit' => $limit, + ); + $query_args = apply_filters( 'pmpromd_pagination_url', $query_args, 'next' ); + ?> + » + +
+ - - - - "> + + + + options)){ - $rh_fields[$field->name] = $field->options; + // Get Register Helper field options + $rh_fields = array(); + if(!empty($pmprorh_registration_fields)) { + foreach($pmprorh_registration_fields as $location) { + foreach($location as $field) { + if(!empty($field->options)){ + $rh_fields[$field->name] = $field->options; + } } } } - } + ?> +
+ - ?> - - -
- - - -

- ID, $avatar_size, NULL, $pu->display_name, array("class"=>"alignright")); ?> -

- - display_name) ) { ?> -

- -

- - description) ) { ?> -

- - description; ?> -

- - -

- - user_email, 'user_email' ); ?> -

- - -

- - membership_levels ) ? $pu->membership_levels : ''; ?> -

- - -

- - startdate < $min_startdate ) { - $min_startdate = $level->startdate; + display_name ) ) { + $heading_classes = array(); + $heading_classes[] = 'pmpro_card_title'; + $heading_classes[] = 'pmpro_font-x-large'; + if ( ! empty( $show_avatar ) ) { + $heading_classes[] = 'pmpro_heading-with-avatar'; } - } - echo ! empty( $min_startdate ) ? date_i18n( get_option( 'date_format' ), $min_startdate ) : ''; + $heading_classes = implode( ' ', $heading_classes ); ?> -

- - pmpro_baddress1)) { ?> -

- - pmpro_baddress1; ?>
- pmpro_baddress2)) - echo $pu->pmpro_baddress2 . "
"; - ?> - pmpro_bcity && $pu->pmpro_bstate) { ?> - pmpro_bcity; ?>, pmpro_bstate; ?> pmpro_bzipcode; ?>
- pmpro_bcountry; ?>
+

+ + ID, $avatar_size, NULL, $pu->display_name, array("class"=>"alignright")); ?> + + +

+ +
+ ID, $avatar_size, NULL, $pu->display_name, array("class"=>"alignright")); ?> +
+ +
+ description) ) { ?> +
+ + description; ?> +
-

- - pmpro_bphone)) { ?> -

- - pmpro_bphone); ?> -

- - +
+ + user_email, 'user_email' ); ?> +
+ + +
+ + membership_levels ) ? $pu->membership_levels : ''; ?> +
+ + +
+ + startdate < $min_startdate ) { + $min_startdate = $level->startdate; + } + } + echo ! empty( $min_startdate ) ? date_i18n( get_option( 'date_format' ), $min_startdate ) : ''; + ?> +
+ + pmpro_baddress1)) { ?> +
+ + pmpro_baddress1; ?>
+ pmpro_baddress2)) + echo $pu->pmpro_baddress2 . "
"; + ?> + pmpro_bcity && $pu->pmpro_bstate) { ?> + pmpro_bcity; ?>, pmpro_bstate; ?> pmpro_bzipcode; ?>
+ pmpro_bcountry; ?>
+ +
+ + pmpro_bphone)) { ?> +
+ + pmpro_bphone); ?> +
+ + $field_val; + // Fix for a trailing space in the 'fields' shortcode attribute. + if ( $field[0] === ' ' ) { + break; + } - // If using PMPro 2.10, try use User Field function to display labels. - if ( function_exists( 'pmpro_get_label_for_user_field_value' ) && ! empty( $field_val ) && ! empty( $meta_field ) ) { - $meta_field = pmpro_get_label_for_user_field_value( $field_val, $meta_field ); - } + // Get the field name and value here. + $field_val = $field[1]; + $meta_field = $pu->$field_val; - if(!empty($meta_field)) - { - ?> -

- - - - $value) - $meta_field[$key] = $rh_fields[$field[1]][$value]; - } - ?> - - - - - + ?> +

+ + + $value) + $meta_field[$key] = $rh_fields[$field[1]][$value]; + } + ?> + + + - - + + + + + -

- + - -
-
-
-

- %s', esc_url( $directory_url ), esc_html__( 'View All Members', 'pmpro-member-directory' ) ); - } + ?> + +

+
+ ID === $current_user->ID ) { - // User viewing their own profile. Show an edit profile link if 'Member Profile Edit Page' is set or dashboard access is allowed. - if ( ! empty( get_option( 'pmpro_member_profile_edit_page_id' ) ) ) { - $edit_profile_url = pmpro_url( 'member_profile_edit' ); - } elseif ( ! pmpro_block_dashboard() ) { - $edit_profile_url = admin_url( 'profile.php' ); - } + if ( ! empty( $directory_url ) ) { + $pmpro_member_profile_action_links['view-directory'] = sprintf( '%s', esc_url( $directory_url ), esc_html__( 'View All Members', 'pmpro-member-directory' ) ); + } - if ( ! empty( $edit_profile_url) ) { - $pmpro_member_profile_action_links['edit-profile'] = sprintf( '%s', esc_url( $edit_profile_url ), esc_html__( 'Edit Profile', 'paid-memberships-pro' ) ); - } - } + if ( ! empty( $pu ) && $pu->ID === $current_user->ID ) { + // User viewing their own profile. Show an edit profile link if 'Member Profile Edit Page' is set or dashboard access is allowed. + if ( ! empty( get_option( 'pmpro_member_profile_edit_page_id' ) ) ) { + $edit_profile_url = pmpro_url( 'member_profile_edit' ); + } elseif ( ! pmpro_block_dashboard() ) { + $edit_profile_url = admin_url( 'profile.php' ); + } + + if ( ! empty( $edit_profile_url) ) { + $pmpro_member_profile_action_links['edit-profile'] = sprintf( '%s', esc_url( $edit_profile_url ), esc_html__( 'Edit Profile', 'paid-memberships-pro' ) ); + } + } - /** - * Filter which links are displayed on the single Member Directory Profile page. - * - * @since 1.0 - * - * @param array $pmpro_member_profile_action_links Can be view-directory, edit-profile, or or custom. - * - * @return array $pmpro_member_profile_action_links - */ - $pmpro_member_profile_action_links = apply_filters( 'pmpromd_member_profile_action_links', $pmpro_member_profile_action_links ); - - $allowed_html = array( - 'a' => array ( - 'class' => array(), - 'href' => array(), - 'id' => array(), - 'target' => array(), - 'title' => array(), - ), - ); - echo wp_kses( implode( pmpro_actions_nav_separator(), $pmpro_member_profile_action_links ), $allowed_html ); - ?> -

- + /** + * Filter which links are displayed on the single Member Directory Profile page. + * + * @since 1.0 + * + * @param array $pmpro_member_profile_action_links Can be view-directory, edit-profile, or or custom. + * + * @return array $pmpro_member_profile_action_links + */ + $pmpro_member_profile_action_links = apply_filters( 'pmpromd_member_profile_action_links', $pmpro_member_profile_action_links ); + + $allowed_html = array( + 'a' => array ( + 'class' => array(), + 'href' => array(), + 'id' => array(), + 'target' => array(), + 'title' => array(), + ), + ); + echo wp_kses( implode( pmpro_actions_nav_separator(), $pmpro_member_profile_action_links ), $allowed_html ); + ?> +
+
+ +
Date: Thu, 14 Nov 2024 13:31:56 -0500 Subject: [PATCH 02/24] Removing unnecessary query data --- templates/directory.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/templates/directory.php b/templates/directory.php index 9242aad..e9803d0 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -99,9 +99,9 @@ function pmpromd_shortcode($atts, $content=null, $code="") // Build SQL into parts to make it easier to add in specific sections to the SQL. $sql_parts = array(); -$sql_parts['SELECT'] = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, u.user_nicename, u.display_name, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership, umf.meta_value as first_name, uml.meta_value as last_name FROM $wpdb->users u "; +$sql_parts['SELECT'] = "SELECT SQL_CALC_FOUND_ROWS u.ID FROM $wpdb->users u "; -$sql_parts['JOIN'] = "LEFT JOIN $wpdb->usermeta umh ON umh.meta_key = 'pmpromd_hide_directory' AND u.ID = umh.user_id LEFT JOIN $wpdb->usermeta umf ON umf.meta_key = 'first_name' AND u.ID = umf.user_id LEFT JOIN $wpdb->usermeta uml ON uml.meta_key = 'last_name' AND u.ID = uml.user_id LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id "; +$sql_parts['JOIN'] = "LEFT JOIN $wpdb->usermeta umh ON umh.meta_key = 'pmpromd_hide_directory' AND u.ID = umh.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id "; $sql_parts['WHERE'] = "WHERE mu.status = 'active' AND (umh.meta_value IS NULL OR umh.meta_value <> '1') AND mu.membership_id > 0 "; @@ -131,6 +131,7 @@ function pmpromd_shortcode($atts, $content=null, $code="") */ $sql_search_where = apply_filters( 'pmpro_member_directory_sql_search_where', $sql_search_where, $s ); + $sql_parts['JOIN'] .= "LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id "; $sql_parts['WHERE'] .= $sql_search_where; } From f149f42338bb24fe5aa5cdc3f476642380ac535d Mon Sep 17 00:00:00 2001 From: David Parker Date: Thu, 14 Nov 2024 13:56:58 -0500 Subject: [PATCH 03/24] Return early when no results, clean up whitespace --- templates/directory.php | 666 ++++++++++++++++++++-------------------- 1 file changed, 329 insertions(+), 337 deletions(-) diff --git a/templates/directory.php b/templates/directory.php index 9242aad..f771702 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -193,90 +193,112 @@ function pmpromd_shortcode($atts, $content=null, $code="") +

+ %s.', 'pmpro-member-directory' ), stripslashes( ucwords( esc_html( $s ) ) ) ) ); - if(!empty($fields)) - { - // Check to see if the Block Editor is used or the shortcode. - if ( strpos( $fields, "\n" ) !== FALSE ) { - $fields = rtrim( $fields, "\n" ); // clear up a stray \n - $fields_array = explode("\n", $fields); // For new block editor. + // If there is a directory URL, display a link to view all members. + if ( ! empty( $directory_url ) ) { + ?> + + +

+ options)) - $rh_fields[$field->name] = $field->options; - } + + if(!empty($fields_array)) + { + for($i = 0; $i < count($fields_array); $i++ ) + $fields_array[$i] = explode(",", trim($fields_array[$i])); + } + } + else + $fields_array = false; + + + /** + * Allow filtering the fields to include on the member directory list. + * + * @since TBD + * + * @param array $fields_array The list of fields to include. + */ + $fields_array = apply_filters( 'pmpro_member_directory_fields', $fields_array ); + + // Get Register Helper field options + $rh_fields = array(); + if(!empty($pmprorh_registration_fields)) { + foreach($pmprorh_registration_fields as $location) { + foreach($location as $field) { + if(!empty($field->options)) + $rh_fields[$field->name] = $field->options; } } - ?> + } + ?> - $avatar_size, - 'fields' => $fields, - 'layout' => $layout, - 'level' => $level, - 'levels' => $levels, - 'limit' => $limit, - 'link' => $link, - 'order_by' => $order_by, - 'order' => $order, - 'show_avatar' => $show_avatar, - 'show_email' => $show_email, - 'show_level' => $show_level, - 'show_search' => $show_search, - 'show_startdate' => $show_startdate, - 'avatar_align' => $avatar_align, - 'fields_array' => $fields_array - ) ); - - do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); ?> + $avatar_size, + 'fields' => $fields, + 'layout' => $layout, + 'level' => $level, + 'levels' => $levels, + 'limit' => $limit, + 'link' => $link, + 'order_by' => $order_by, + 'order' => $order, + 'show_avatar' => $show_avatar, + 'show_email' => $show_email, + 'show_level' => $show_level, + 'show_search' => $show_search, + 'show_startdate' => $show_startdate, + 'avatar_align' => $avatar_align, + 'fields_array' => $fields_array + ) ); + + do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); ?> + +
-
- - - - + +
+ - - - ID); - $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); - $fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); - $count++; - ?> - "> - - - - - - - - - - - - - - - - - - - - - - -
@@ -308,186 +330,112 @@ function pmpromd_shortcode($atts, $content=null, $code="")  
- - ID, $avatar_size, NULL, $auser->user_nicename ); ?> - - ID, $avatar_size, NULL, $auser->user_nicename ); ?> - - -

- - - - - -

-
- user_email, 'user_email' ); ?> - - {$field[1]}; - if(!empty($meta_field)) - { - ?> -

- - - - $value) - $meta_field[$key] = $rh_fields[$field[1]][$value]; - } - ?> - - - - - - - - {$field[1]}, $field[1] ); ?> - -

- -
- ID ); - $membership_levels = array(); - if ( ! isset( $levels ) ) { - // Show all the user's levels. - foreach ( $alluserlevels as $curlevel ) { - $membership_levels[] = $curlevel->name; - } - } else { - $levels_array = explode(',', $levels); - // Show only the levels included in the directory. - foreach ( $alluserlevels as $curlevel ) { - if ( in_array( $curlevel->id, $levels_array) ) { - $membership_levels[] = $curlevel->name; - } - } - } - $auser->membership_levels = implode( ', ', $membership_levels ); - echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; - ?> - - membership_level->startdate); ?> -
+ + ID); + $count = 0; + foreach($theusers as $auser) + { + $auser = get_userdata($auser->ID); $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); - $user_identifier = pmpromd_user_identifier(); $fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); + $count++; ?> -
+ "> -
+ - ID, $avatar_size, NULL, $auser->display_name); ?> + ID, $avatar_size, NULL, $auser->user_nicename ); ?> - ID, $avatar_size, NULL, $auser->display_name); ?> + ID, $avatar_size, NULL, $auser->user_nicename ); ?> -
+ -

- - - - - -

+ +

+ + + + + +

+ -

- + user_email, 'user_email' ); ?> -

+ + + + {$field[1]}; + if(!empty($meta_field)) + { + ?> +

+ + + + $value) + $meta_field[$key] = $rh_fields[$field[1]][$value]; + } + ?> + + + + + + + + {$field[1]}, $field[1] ); ?> + +

+ + + -

- + ID ); $membership_levels = array(); @@ -508,119 +456,163 @@ function pmpromd_shortcode($atts, $content=null, $code="") $auser->membership_levels = implode( ', ', $membership_levels ); echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; ?> -

+ -

- + membership_level->startdate); ?> -

+ - + + + + + + + + + ID); + $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); + $user_identifier = pmpromd_user_identifier(); + $fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); + ?> +
+ +
+ + ID, $avatar_size, NULL, $auser->display_name); ?> + + ID, $avatar_size, NULL, $auser->display_name); ?> + +
+ +

+ + + + + +

+ +

+ + user_email, 'user_email' ); ?> +

+ + +

+ + ID ); + $membership_levels = array(); + if ( ! isset( $levels ) ) { + // Show all the user's levels. + foreach ( $alluserlevels as $curlevel ) { + $membership_levels[] = $curlevel->name; + } + } else { + $levels_array = explode(',', $levels); + // Show only the levels included in the directory. + foreach ( $alluserlevels as $curlevel ) { + if ( in_array( $curlevel->id, $levels_array) ) { + $membership_levels[] = $curlevel->name; + } + } } + $auser->membership_levels = implode( ', ', $membership_levels ); + echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; + ?> +

+ + +

+ + membership_level->startdate); ?> +

+ + {$field[1]}; - if(!empty($meta_field)) - { - ?> -

- - - - $value) - $meta_field[$key] = $rh_fields[$field[1]][$value]; - } - ?> - - - + $meta_field = $auser->{$field[1]}; + if(!empty($meta_field)) + { + ?> +

+ - + - - {$field[1]}, $field[1] ); ?> - $value) + $meta_field[$key] = $rh_fields[$field[1]][$value]; } ?> -

+ + + + + + + {$field[1]}, $field[1] ); ?> + +

+ - - - -
- + + + +
+ -
- -

- - %s.','pmpro-member-directory'), stripslashes( ucwords(esc_html($s))) ); - if(!empty($directory_url)) - { - ?> - - -

- +
From aa8a5f6702b9efbe8f9abceb04adf280604ca9bf Mon Sep 17 00:00:00 2001 From: David Parker Date: Thu, 14 Nov 2024 14:30:43 -0500 Subject: [PATCH 04/24] Weaving together logic for different layouts --- templates/directory.php | 456 +++++++++++++++++----------------------- 1 file changed, 197 insertions(+), 259 deletions(-) diff --git a/templates/directory.php b/templates/directory.php index f771702..09833ac 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -296,6 +296,7 @@ function pmpromd_shortcode($atts, $content=null, $code="") @@ -312,11 +313,6 @@ function pmpromd_shortcode($atts, $content=null, $code="") - - - + + + ID); - $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); - $fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); - $count++; - ?> - "> - - - - - - - - - "> + +
+ {$field[1]}; - if(!empty($meta_field)) - { - ?> -

- - - - $value) - $meta_field[$key] = $rh_fields[$field[1]][$value]; - } - ?> - - - - - - - - {$field[1]}, $field[1] ); ?> - -

- - - - -
- - - + // Show the user's avatar. + if ( ! empty( $show_avatar ) ) { + if ( $layout == 'table' ) { + ?> + + +
-
+ ID, $avatar_size, NULL, $auser->display_name); ?> + + ID, $avatar_size, NULL, $auser->display_name); ?> - + - -
- - @@ -327,287 +323,229 @@ function pmpromd_shortcode($atts, $content=null, $code="") + +  
- - ID, $avatar_size, NULL, $auser->user_nicename ); ?> - - ID, $avatar_size, NULL, $auser->user_nicename ); ?> - - -

- - - - - -

-
- user_email, 'user_email' ); ?> - - ID); + $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); + $fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); + $count++; + + // Show the header for the user. + if ( $layout == 'table' ) { + ?> +
- ID ); - $membership_levels = array(); - if ( ! isset( $levels ) ) { - // Show all the user's levels. - foreach ( $alluserlevels as $curlevel ) { - $membership_levels[] = $curlevel->name; - } - } else { - $levels_array = explode(',', $levels); - // Show only the levels included in the directory. - foreach ( $alluserlevels as $curlevel ) { - if ( in_array( $curlevel->id, $levels_array) ) { - $membership_levels[] = $curlevel->name; - } - } - } - $auser->membership_levels = implode( ', ', $membership_levels ); - echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; - ?> - - membership_level->startdate); ?> - + + ID, $avatar_size, NULL, $auser->user_nicename ); ?> + + ID, $avatar_size, NULL, $auser->user_nicename ); ?> +
+ } + + // Show the user's display name. + if ( $layout == 'table' ) { + // Open the td. + ?> +

+ + + + + +

ID); - $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); - $user_identifier = pmpromd_user_identifier(); - $fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); + if ( $layout == 'table' ) { + // Close the td. + ?> -
- -
- - ID, $avatar_size, NULL, $auser->display_name); ?> - - ID, $avatar_size, NULL, $auser->display_name); ?> - -
- -

- - - - - -

- -

- - user_email, 'user_email' ); ?> -

- - -

- - ID ); - $membership_levels = array(); - if ( ! isset( $levels ) ) { - // Show all the user's levels. - foreach ( $alluserlevels as $curlevel ) { - $membership_levels[] = $curlevel->name; - } - } else { - $levels_array = explode(',', $levels); - // Show only the levels included in the directory. - foreach ( $alluserlevels as $curlevel ) { - if ( in_array( $curlevel->id, $levels_array) ) { - $membership_levels[] = $curlevel->name; - } - } - } - $auser->membership_levels = implode( ', ', $membership_levels ); - echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; - ?> -

- - -

- - membership_level->startdate); ?> -

- + < class="pmpro_member_directory_email"> + user_email, 'user_email' ); ?> + > + + + < class="pmpro_member_directory_level"> + ID ); + $membership_levels = array(); + if ( ! isset( $levels ) ) { + // Show all the user's levels. + foreach ( $alluserlevels as $curlevel ) { + $membership_levels[] = $curlevel->name; } - - // Fix for a trailing space in the 'fields' shortcode attribute. - if ( $field[0] === '' ) { - break; + } else { + $levels_array = explode(',', $levels); + // Show only the levels included in the directory. + foreach ( $alluserlevels as $curlevel ) { + if ( in_array( $curlevel->id, $levels_array) ) { + $membership_levels[] = $curlevel->name; + } } + } + $auser->membership_levels = implode( ', ', $membership_levels ); + echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; + ?> + > + {$field[1]}; - if(!empty($meta_field)) - { + // Show the user's start date. + if ( ! empty( $show_startdate ) ) { + // If the layout is not a table, print "Start Date" as a header. + if ( $layout !== 'table' ) { + ?> + + + < class="pmpro_member_directory_date"> + membership_level->startdate ); ?> + > + {$field[1]}; + if ( ! empty( $meta_field ) ) { + ?> +

+ -

- - - - + + $value) { + $meta_field[$key] = $rh_fields[$field[1]][$value]; } - elseif(is_array($meta_field)) - { - //this is a general array, check for Register Helper options first - if(!empty($rh_fields[$field[1]])) { - foreach($meta_field as $key => $value) - $meta_field[$key] = $rh_fields[$field[1]][$value]; - } - ?> - - - - - - - - {$field[1]}, $field[1] ); ?> - -

+ ?> + + + + + + + {$field[1]}, $field[1] ); } - } - } - ?> - - - + + < class="pmpro_member_directory_link"> + + > + + +
+ + +
Date: Thu, 14 Nov 2024 14:35:04 -0500 Subject: [PATCH 05/24] Fixing div formatting --- templates/directory.php | 69 ++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/templates/directory.php b/templates/directory.php index 09833ac..b76e213 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -404,40 +404,49 @@ function pmpromd_shortcode($atts, $content=null, $code="") if ( ! empty( $show_email ) ) { ?> < class="pmpro_member_directory_email"> - user_email, 'user_email' ); ?> + + + user_email, 'user_email' ); + ?> > - - < class="pmpro_member_directory_level"> ID ); - $membership_levels = array(); - if ( ! isset( $levels ) ) { - // Show all the user's levels. - foreach ( $alluserlevels as $curlevel ) { + // If the layout is not a table, print "level" as a label. + if ( $layout !== 'table' ) { + ?> + + ID ); + $membership_levels = array(); + if ( ! isset( $levels ) ) { + // Show all the user's levels. + foreach ( $alluserlevels as $curlevel ) { + $membership_levels[] = $curlevel->name; + } + } else { + $levels_array = explode(',', $levels); + // Show only the levels included in the directory. + foreach ( $alluserlevels as $curlevel ) { + if ( in_array( $curlevel->id, $levels_array) ) { $membership_levels[] = $curlevel->name; } - } else { - $levels_array = explode(',', $levels); - // Show only the levels included in the directory. - foreach ( $alluserlevels as $curlevel ) { - if ( in_array( $curlevel->id, $levels_array) ) { - $membership_levels[] = $curlevel->name; - } - } } - $auser->membership_levels = implode( ', ', $membership_levels ); - echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; + } + $auser->membership_levels = implode( ', ', $membership_levels ); + echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; ?> > - - < class="pmpro_member_directory_date"> - membership_level->startdate ); ?> + + + membership_level->startdate ); + ?> > Date: Thu, 14 Nov 2024 14:53:21 -0500 Subject: [PATCH 06/24] Whitespace and WPCS --- templates/directory.php | 110 +++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 59 deletions(-) diff --git a/templates/directory.php b/templates/directory.php index bdc95ba..2fb2cbc 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -101,57 +101,56 @@ function pmpromd_shortcode($atts, $content=null, $code="") $end = $pn * $limit; $start = $end - $limit; -// Build SQL into parts to make it easier to add in specific sections to the SQL. -$sql_parts = array(); + // Build SQL into parts to make it easier to add in specific sections to the SQL. + $sql_parts = array(); -$sql_parts['SELECT'] = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, u.user_nicename, u.display_name, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership, umf.meta_value as first_name, uml.meta_value as last_name FROM $wpdb->users u "; + $sql_parts['SELECT'] = "SELECT SQL_CALC_FOUND_ROWS u.ID, u.user_login, u.user_email, u.user_nicename, u.display_name, UNIX_TIMESTAMP(u.user_registered) as joindate, mu.membership_id, mu.initial_payment, mu.billing_amount, mu.cycle_period, mu.cycle_number, mu.billing_limit, mu.trial_amount, mu.trial_limit, UNIX_TIMESTAMP(mu.startdate) as startdate, UNIX_TIMESTAMP(mu.enddate) as enddate, m.name as membership, umf.meta_value as first_name, uml.meta_value as last_name FROM $wpdb->users u "; -$sql_parts['JOIN'] = "LEFT JOIN $wpdb->usermeta umh ON umh.meta_key = 'pmpromd_hide_directory' AND u.ID = umh.user_id LEFT JOIN $wpdb->usermeta umf ON umf.meta_key = 'first_name' AND u.ID = umf.user_id LEFT JOIN $wpdb->usermeta uml ON uml.meta_key = 'last_name' AND u.ID = uml.user_id LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id "; + $sql_parts['JOIN'] = "LEFT JOIN $wpdb->usermeta umh ON umh.meta_key = 'pmpromd_hide_directory' AND u.ID = umh.user_id LEFT JOIN $wpdb->usermeta umf ON umf.meta_key = 'first_name' AND u.ID = umf.user_id LEFT JOIN $wpdb->usermeta uml ON uml.meta_key = 'last_name' AND u.ID = uml.user_id LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id LEFT JOIN $wpdb->pmpro_memberships_users mu ON u.ID = mu.user_id LEFT JOIN $wpdb->pmpro_membership_levels m ON mu.membership_id = m.id "; -$sql_parts['WHERE'] = "WHERE mu.status = 'active' AND (umh.meta_value IS NULL OR umh.meta_value <> '1') AND mu.membership_id > 0 "; + $sql_parts['WHERE'] = "WHERE mu.status = 'active' AND (umh.meta_value IS NULL OR umh.meta_value <> '1') AND mu.membership_id > 0 "; -$sql_parts['GROUP'] = "GROUP BY u.ID "; + $sql_parts['GROUP'] = "GROUP BY u.ID "; -// Clean up order_by to only include text, underscores and periods. -$order_by = preg_replace( '/[^a-z._]/', '', $order_by ); -$sql_parts['ORDER'] = "ORDER BY ". esc_sql( $order_by ) . " " . esc_sql( $order ) . " "; + // Clean up order_by to only include text, underscores and periods. + $order_by = preg_replace( '/[^a-z._]/', '', $order_by ); + $sql_parts['ORDER'] = "ORDER BY ". esc_sql( $order_by ) . " " . esc_sql( $order ) . " "; -$sql_parts['LIMIT'] = "LIMIT $start, $limit"; + $sql_parts['LIMIT'] = "LIMIT $start, $limit"; -if( $s ) { - $sql_search_where = " - AND ( - u.user_login LIKE '%" . esc_sql( $s ) . "%' - OR u.user_email LIKE '%" . esc_sql( $s ) . "%' - OR u.display_name LIKE '%" . esc_sql( $s ) . "%' - OR um.meta_value LIKE '%" . esc_sql( $s ) . "%' - ) - "; + if( $s ) { + $sql_search_where = " + AND ( + u.user_login LIKE '%" . esc_sql( $s ) . "%' + OR u.user_email LIKE '%" . esc_sql( $s ) . "%' + OR u.display_name LIKE '%" . esc_sql( $s ) . "%' + OR um.meta_value LIKE '%" . esc_sql( $s ) . "%' + ) + "; - /** - * Allow filtering the member directory search SQL to be used. - * - * @since TBD - * - * @param string $sql_search_where The member directory search SQL to be used. - * @param string $search_text The search text used. - */ - $sql_search_where = apply_filters( 'pmpro_member_directory_sql_search_where', $sql_search_where, $s ); + /** + * Allow filtering the member directory search SQL to be used. + * + * @since TBD + * + * @param string $sql_search_where The member directory search SQL to be used. + * @param string $search_text The search text used. + */ + $sql_search_where = apply_filters( 'pmpro_member_directory_sql_search_where', $sql_search_where, $s ); - $sql_parts['WHERE'] .= $sql_search_where; -} - -// If levels are passed in. -if ( $levels ) { - $levels = preg_replace('/[^0-9,]/', '', $levels ); // Only allow commas and numeric values. - $sql_parts['WHERE'] .= "AND mu.membership_id IN(" . esc_sql($levels) . ") "; -} + $sql_parts['WHERE'] .= $sql_search_where; + } -// Allow filters for SQL parts. -$sql_parts = apply_filters( 'pmpro_member_directory_sql_parts', $sql_parts, $levels, $s, $pn, $limit, $start, $end, $order_by, $order ); + // If levels are passed in. + if ( $levels ) { + $levels = preg_replace('/[^0-9,]/', '', $levels ); // Only allow commas and numeric values. + $sql_parts['WHERE'] .= "AND mu.membership_id IN(" . esc_sql($levels) . ") "; + } -$sqlQuery = $sql_parts['SELECT'] . $sql_parts['JOIN'] . $sql_parts['WHERE'] . $sql_parts['GROUP'] . $sql_parts['ORDER'] . $sql_parts['LIMIT']; + // Allow filters for SQL parts. + $sql_parts = apply_filters( 'pmpro_member_directory_sql_parts', $sql_parts, $levels, $s, $pn, $limit, $start, $end, $order_by, $order ); + $sqlQuery = $sql_parts['SELECT'] . $sql_parts['JOIN'] . $sql_parts['WHERE'] . $sql_parts['GROUP'] . $sql_parts['ORDER'] . $sql_parts['LIMIT']; $sqlQuery = apply_filters("pmpro_member_directory_sql", $sqlQuery, $levels, $s, $pn, $limit, $start, $end, $order_by, $order); @@ -164,8 +163,6 @@ function pmpromd_shortcode($atts, $content=null, $code="") $theusers = apply_filters( 'pmpromd_user_directory_results', $theusers ); - $user_identifier = pmpromd_user_identifier(); - ob_start(); ?> @@ -227,8 +224,7 @@ function pmpromd_shortcode($atts, $content=null, $code="") return $temp_content; } - if(!empty($fields)) - { + if ( ! empty( $fields ) ) { // Check to see if the Block Editor is used or the shortcode. if ( strpos( $fields, "\n" ) !== FALSE ) { $fields = rtrim( $fields, "\n" ); // clear up a stray \n @@ -238,14 +234,14 @@ function pmpromd_shortcode($atts, $content=null, $code="") $fields_array = explode(";",$fields); } - if(!empty($fields_array)) - { - for($i = 0; $i < count($fields_array); $i++ ) - $fields_array[$i] = explode(",", trim($fields_array[$i])); + if ( ! empty( $fields_array ) ) { + for ( $i = 0; $i < count( $fields_array ); $i++ ) { + $fields_array[$i] = explode( ",", trim( $fields_array[$i] ) ); + } } - } - else + } else { $fields_array = false; + } /** @@ -259,11 +255,12 @@ function pmpromd_shortcode($atts, $content=null, $code="") // Get Register Helper field options $rh_fields = array(); - if(!empty($pmprorh_registration_fields)) { - foreach($pmprorh_registration_fields as $location) { - foreach($location as $field) { - if(!empty($field->options)) + if ( ! empty( $pmprorh_registration_fields ) ) { + foreach ( $pmprorh_registration_fields as $location ) { + foreach ($location as $field) { + if ( ! empty( $field->options ) ) { $rh_fields[$field->name] = $field->options; + } } } } @@ -296,12 +293,7 @@ function pmpromd_shortcode($atts, $content=null, $code="") do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); ?> -
- +
Date: Fri, 15 Nov 2024 13:18:42 -0500 Subject: [PATCH 07/24] Improve plugin file structure and organization --- includes/admin.php | 198 ++++++++++++++ includes/functions.php | 201 ++++++++++++++ pmpro-member-directory.php | 520 +++++-------------------------------- 3 files changed, 458 insertions(+), 461 deletions(-) create mode 100644 includes/admin.php create mode 100644 includes/functions.php diff --git a/includes/admin.php b/includes/admin.php new file mode 100644 index 0000000..fbf91ca --- /dev/null +++ b/includes/admin.php @@ -0,0 +1,198 @@ +ID ) { + + $pu = pmpromd_get_user(); + + if ( $pu ) { + + $edit_member_link = add_query_arg( array( 'page' => 'pmpro-member', 'user_id' => $pu->ID, 'pmpro_member_edit_panel' => 'memberships' ), admin_url( 'admin.php' ) ); + $admin_bar->add_menu( array( + 'id' => 'pmpromd-edit-member', + 'title' => esc_html__( 'Edit Member', 'pmpro-member-directory' ), + 'href' => esc_url( $edit_member_link ), + 'meta' => array( + 'title' => __( 'Edit Member', 'pmpro-member-directory' ), + ), + )); + + } + } + +} +add_action( 'admin_bar_menu', 'pmpromd_add_edit_profile', 100 ); + +/** + * Add a page setting for the Member Directory and Profile pages. + * + * @param array $pages Array of settings for the PMPro settings page. + */ +function pmpromd_extra_page_settings( $pages ) { + $pages['directory'] = array( + 'title' => esc_html__( 'Directory', 'pmpro-member-directory' ), + 'content' => '[pmpro_member_directory]', + 'hint' => esc_html__( 'Include the shortcode [pmpro_member_directory].', 'pmpro-member-directory' ), + ); + $pages['profile'] = array( + 'title' => esc_html__( 'Profile', 'pmpro-member-directory' ), + 'content' => '[pmpro_member_profile]', + 'hint' => esc_html__( 'Include the shortcode [pmpro_member_profile].', 'pmpro-member-directory' ), + ); + + return $pages; +} +add_filter( 'pmpro_extra_page_settings', 'pmpromd_extra_page_settings'); + +/** + * On Page Settings Save, Flush Rewrite Rules + */ +function pmpromd_pagesettings_flush() { + if ( + ! empty( $_REQUEST['page'] ) && + $_REQUEST['page'] == 'pmpro-pagesettings' && //Are we on the PMPro Page Settings + ! empty( $_REQUEST['savesettings']) && //Are we hitting the save button + ! empty( $_REQUEST['profile_page_id'] ) //Is there a profile page present + ) { + flush_rewrite_rules( true ); + } +} +add_action( 'admin_init', 'pmpromd_pagesettings_flush', 4 ); + +/** + * We're saving a page, is it a Profile page + */ +function pmpromd_page_save_flush( $post_id ) { + global $pmpro_pages; + if( ! empty( $pmpro_pages['profile'] ) && + (int)$pmpro_pages['profile'] == $post_id && + did_action( 'init' ) + ) { + flush_rewrite_rules( true ); + } +} +add_action( 'save_post', 'pmpromd_page_save_flush', 10, 1 ); + +/** + * Run an upgrade check to compare versions and flush rewrite rules + * + * @since 1.2 + * + * @return void + */ +function pmpromd_check_for_upgrade() { + + if ( ! function_exists( 'pmpro_init' ) ) { + return; + } + + $pmpromd_db_version = get_option("pmpro_md_db_version"); + + if( empty( $pmpromd_db_version ) || version_compare( $pmpromd_db_version, '1.2', '<' ) ) { + flush_rewrite_rules( true ); + pmpro_setOption("md_db_version", "1.2"); + } + +} +add_action( 'admin_init', 'pmpromd_check_for_upgrade' ); + +/** + * Strip the [pmpro_member_directory] or [pmpro_member_profile] shortcode and blocks from content if the current user can't edit users. + * + * @since TBD + * + * @return mixed The content with the shortcode removed. Will be the same type as the input. + */ +function pmpromd_maybe_strip_shortcodes( $content ) { + // If the user can edit users, we don't need to strip the shortcode. + if ( current_user_can( 'edit_users' ) ) { + return $content; + } + + // If an array is passed in, filter all elements recursively. + if ( is_array( $content ) ) { + foreach ( $content as $key => $value ) { + $content[ $key ] = pmpromd_maybe_strip_shortcodes( $value ); + } + return $content; + } + + // If we're not looking at a string, just return it. + if ( ! is_string( $content ) ) { + return $content; + } + + // Okay, we have a string, figure out the regex. + $shortcodeRegex = get_shortcode_regex( array( 'pmpro_member_directory', 'pmpro_member_profile' ) ); + + // Remove various blocks. + $blockWrapperPatterns = array( + "", + "", + "//", + "//", + "/\s*$shortcodeRegex\s*/s", + "/$shortcodeRegex/" + ); + + $content = preg_replace( $blockWrapperPatterns, '', $content ); + + return $content; +} +add_filter( 'content_save_pre', 'pmpromd_maybe_strip_shortcodes' ); +add_filter( 'excerpt_save_pre', 'pmpromd_maybe_strip_shortcodes' ); +add_filter( 'widget_update_callback', 'pmpromd_maybe_strip_shortcodes' ); + +/** + * Only allow those with the edit_users capability + * to use the Directory or Profile shortcodes in post_meta. + * + * @since TBD + * @param int $meta_id ID of the meta data entry. + * @param int $object_id ID of the object the meta is attached to. + * @param string $meta_key Meta key. + * @param mixed $_meta_value Meta value. + * @return void + */ +function pmpromd_maybe_strip_shortcodes_from_post_meta( $meta_id, $object_id, $meta_key, $_meta_value ) { + // Bail if the value is not a string or array. + if ( ! is_string( $_meta_value ) && ! is_array( $_meta_value ) ) { + return; + } + + // Strip the shortcode from the meta value. + $stripped_value = pmpromd_maybe_strip_shortcodes( $_meta_value ); + + // If there was a change, save our stripped version. + if ( $stripped_value !== $_meta_value ) { + update_post_meta( $object_id, $meta_key, $stripped_value ); + } +} +add_action( 'updated_post_meta', 'pmpromd_maybe_strip_shortcodes_from_post_meta', 10, 4 ); + +/** + * Function to add links to the plugin row meta + */ +function pmpromd_plugin_row_meta( $links, $file ) { + if ( strpos( $file, 'pmpro-member-directory.php' ) !== false ) { + $new_links = array( + '' . __( 'Docs', 'pmpro-member-directory' ) . '', + '' . __( 'Support', 'pmpro-member-directory' ) . '', + ); + $links = array_merge( $links, $new_links ); + } + + return $links; +} +add_filter( 'plugin_row_meta', 'pmpromd_plugin_row_meta', 10, 2 ); diff --git a/includes/functions.php b/includes/functions.php new file mode 100644 index 0000000..bc1d6ba --- /dev/null +++ b/includes/functions.php @@ -0,0 +1,201 @@ + sprintf( __('Hide from %s?','pmpro-member-directory'), $directory_page_title ), + 'profile' => 'only', + 'required' => false + ) + ) + ); +} +add_action( 'init', 'pmpromd_add_user_fields' ); + +/** + * Filters the name to display for the member in the directory or profile page. + * + * @since 1.0 + * + * @param object $user The WP_User object for the profile. + * @param string $display_name The name to display for the user. + */ +function pmpro_member_directory_get_member_display_name( $user ) { + // Make sure we have a user. + if ( ! $user instanceof WP_User ) { + return ''; + } + + // Get their display name. + $display_name = apply_filters( 'pmpro_member_directory_display_name', $user->display_name, $user ); + + return $display_name; +} + +/** + * Filters the user identifier used in permalinks + * + * @since 1.2.0 + * + * @param string $display_name The name to display for the user. + */ +function pmpromd_user_identifier() { + /** + * Filter to change how user identifiers are presented. Choose between slug and ID + * Note: Value is case sensitive + * + * @since 1.2.0 + */ + return apply_filters( 'pmpromd_user_identifier', 'slug' ); +} + +/** + * Gets user based on their identifier + * + * @since 1.2.0 + * + * @param object The user object + */ +function pmpromd_get_user_by_identifier( $value ) { + $user_identifier = pmpromd_user_identifier(); + return get_user_by( $user_identifier, sanitize_text_field( $value ) ); +} + +/** + * Gets a user from the pu URL value + * + * @since 1.2.0 + * + */ +function pmpromd_get_user( $user_id = false ){ + global $wp_query, $current_user; + + if ( $user_id ) { + //We're specifying which user we want to display + $pu = get_user_by( 'id', intval( $user_id ) ); + } elseif ( ! empty( $wp_query->get( 'pu' ) ) ) { + //Using the new permalinks /profile/user + $pu = pmpromd_get_user_by_identifier( $wp_query->get( 'pu' ) ); + } elseif ( ! empty( $_REQUEST['pu'] ) ) { + //Using old url structure /profile/?pu=user + $pu = pmpromd_get_user_by_identifier( $_REQUEST['pu'] ); + } elseif ( ! empty( $current_user->ID ) ) { + $pu = $current_user; + } else { + $pu = false; + } + + return $pu; +} + +/** + * We determine that the URL base is for the profile and then set up the rewrite rule + */ +function pmpromd_custom_rewrite_rules() { + global $pmpro_pages; + + if ( empty( $pmpro_pages ) || empty( $pmpro_pages['profile'] ) ) { + return; + } + + $profile_permalink = get_the_permalink( $pmpro_pages['profile'] ); + $base_site_url = get_site_url(); + $profile_base = str_replace( $base_site_url . '/', '', $profile_permalink ); + + add_rewrite_rule( + $profile_base.'([^/]+)/?$', + 'index.php?pagename=' . $profile_base . '&pu=$matches[1]', + 'top' + ); +} +add_action( 'init', 'pmpromd_custom_rewrite_rules', 10 ); + +/** + * Adding in the ?pu parameter so that we can retrieve the value from the pretty permalink + */ +function pmpromd_custom_query_vars( $query_vars ) { + $query_vars[] = 'pu'; + return $query_vars; +} +add_filter( 'query_vars', 'pmpromd_custom_query_vars', 10, 1 ); + +/** + * Redirect from the OLD profile URL to the new URL's + */ +function pmpromd_redirect_profile_links() { + if ( ! empty( $_REQUEST['pu'] ) ) { + $structure = get_option( 'permalink_structure' ); + if ( ! empty( $structure ) ) { + wp_redirect( pmpromd_build_profile_url( $_REQUEST['pu'], false, true ), 302, 'WordPress' ); + exit(); + } + } +} +add_action( 'init', 'pmpromd_redirect_profile_links' ); + +/** + * Build profile URL + */ +function pmpromd_build_profile_url( $pu, $profile_url = false, $separator = false ) { + global $pmpro_pages; + + if ( ! empty( $pmpro_pages['profile'] ) && ! $profile_url ) { + $profile_url = apply_filters( 'pmpromd_profile_url', get_permalink( $pmpro_pages['profile'] ) ); + } + + $structure = get_option( 'permalink_structure' ); + + if ( is_object( $pu ) ) { + //We can't use 'slug' directly when getting the user nicename + $user_identifier = strtolower( pmpromd_user_identifier() ); + + if ( $user_identifier == 'id' ) { + $pu = $pu->ID; + } else { + $pu = $pu->user_nicename; + } + } + + if ( empty( $pu ) ) { + return ''; + } + + if ( empty( $structure ) ) { + //We're using plain permalinks here. Query parameters to the rescue! + return add_query_arg( array( 'pu' => $pu ), $profile_url ); + } + + if ( strpos( $structure, 'post_id' ) !== FALSE ) { + //Numeric permalinks don't have a trailing slash for some readon + $separator = true; + } + + if ( $separator ) { + return $profile_url . '/' . sanitize_title( $pu ); + } else { + return $profile_url . sanitize_title( $pu ); + } +} diff --git a/pmpro-member-directory.php b/pmpro-member-directory.php index 2c6bd6f..e50a077 100644 --- a/pmpro-member-directory.php +++ b/pmpro-member-directory.php @@ -10,120 +10,83 @@ Domain Path: /languages */ +// Definitions define( 'PMPRO_MEMBER_DIRECTORY_VERSION', '1.2.6' ); +define( 'PMPRO_MEMBER_DIRECTORY_BASE_FILE', __FILE__ ); +define( 'PMPRO_MEMBER_DIRECTORY_DIR', dirname( __FILE__ ) ); +define( 'PMPRO_MEMBER_DIRECTORY_BASENAME', plugin_basename( __FILE__ ) ); +/* TO DO: Is this needed? */ global $pmpromd_options; -$path = dirname(__FILE__); -$custom_dir = get_stylesheet_directory()."/paid-memberships-pro/pmpro-member-directory/"; -$custom_directory_file = $custom_dir."directory.php"; -$custom_profile_file = $custom_dir."profile.php"; +// Load directory or profile templates from theme, then from plugin. +$custom_dir = get_stylesheet_directory() . '/paid-memberships-pro/pmpro-member-directory/'; +$custom_directory_file = $custom_dir . 'directory.php'; +$custom_profile_file = $custom_dir . 'profile.php'; +file_exists( $custom_directory_file ) ? require_once( $custom_directory_file ) : require_once( PMPRO_MEMBER_DIRECTORY_DIR . '/templates/directory.php' ); +file_exists( $custom_profile_file ) ? require_once( $custom_profile_file ) : require_once( PMPRO_MEMBER_DIRECTORY_DIR . '/templates/profile.php' ); -//load custom or default templates -if(file_exists($custom_directory_file)) - require_once($custom_directory_file); -else - require_once($path . "/templates/directory.php"); -if(file_exists($custom_profile_file)) - require_once($custom_profile_file); -else - require_once($path . "/templates/profile.php"); - -require_once($path . "/blocks/blocks.php"); //localization functions +// Includes +require_once( PMPRO_MEMBER_DIRECTORY_DIR . '/blocks/blocks.php'); +require_once( PMPRO_MEMBER_DIRECTORY_DIR . '/includes/admin.php' ); +require_once( PMPRO_MEMBER_DIRECTORY_DIR . '/includes/functions.php' ); +/** + * Load the languages folder for translations. + */ function pmpromd_load_textdomain() { load_plugin_textdomain( 'pmpro-member-directory', false, basename( dirname( __FILE__ ) ) . '/languages' ); } -add_action( 'init', 'pmpromd_load_textdomain' ); +add_action( 'plugins_loaded', 'pmpromd_load_textdomain' ); +/** + * Register the Member Directory styles. + */ function pmpromd_register_styles() { - //load stylesheet (check child theme, then parent theme, then plugin folder) - if(file_exists(get_stylesheet_directory()."/paid-memberships-pro/member-directory/css/pmpro-member-directory.css")) - wp_register_style( 'pmpro-member-directory-styles', get_stylesheet_directory_uri()."/paid-memberships-pro/member-directory/css/pmpro-member-directory.css"); - elseif(file_exists(get_template_directory()."/paid-memberships-pro/member-directory/css/pmpro-member-directory.css")) - wp_register_style( 'pmpro-member-directory-styles', get_template_directory_uri()."/paid-memberships-pro/member-directory/css/pmpro-member-directory.css"); - elseif(function_exists("pmpro_https_filter")) - wp_register_style( 'pmpro-member-directory-styles', pmpro_https_filter(plugins_url( 'css/pmpro-member-directory.css', __FILE__ ) ), NULL, ""); - else - wp_register_style( 'pmpro-member-directory-styles', plugins_url( 'css/pmpro-member-directory.css', __FILE__ ) ); - wp_enqueue_style( 'pmpro-member-directory-styles' ); - - $custom_css = '#wpadminbar #wp-admin-bar-pmpromd-edit-profile .ab-item:before { content: "\f110"; top: 3px; }'; - - wp_add_inline_style( 'pmpro-member-directory-styles', $custom_css ); - -} -add_action( 'wp_enqueue_scripts', 'pmpromd_register_styles' ); - -function pmpromd_extra_page_settings($pages) { - $pages['directory'] = array('title'=>'Directory', 'content'=>'[pmpro_member_directory]', 'hint'=>'Include the shortcode [pmpro_member_directory].'); - $pages['profile'] = array('title'=>'Profile', 'content'=>'[pmpro_member_profile]', 'hint'=>'Include the shortcode [pmpro_member_profile].'); - return $pages; -} -add_action('pmpro_extra_page_settings', 'pmpromd_extra_page_settings'); - -//show the option to hide from directory on edit user profile -function pmpromd_show_extra_profile_fields($user) -{ - global $pmpro_pages; - - if ( empty( $pmpro_pages['member_profile_edit'] ) || ! is_page( $pmpro_pages['member_profile_edit'] ) ) { -?> -

- - - - - - - -
- - -
- -
- - -
-get( 'Version' ); + wp_register_style( + 'pmpro-member-directory-custom-styles', + get_stylesheet_directory_uri() . '/paid-memberships-pro/member-directory/css/pmpro-member-directory.css', + array(), + $theme_version + ); + } elseif ( file_exists( get_template_directory() . '/paid-memberships-pro/member-directory/css/pmpro-member-directory.css' ) ) { + $theme_version = wp_get_theme()->parent()->get( 'Version' ); + wp_register_style( + 'pmpro-member-directory-custom-styles', + get_template_directory_uri() . '/paid-memberships-pro/member-directory/css/pmpro-member-directory.css', + array(), + $theme_version + ); } - - if ( is_page( $pmpro_pages['member_profile_edit'] ) ) { - if ( ! isset( $_REQUEST['submit'] ) ) { - return false; - } + // Enqueue the custom stylesheet if it exists, otherwise enqueue the default stylesheet. + if ( wp_style_is( 'pmpro-member-directory-custom-styles', 'registered' ) ) { + wp_enqueue_style( 'pmpro-member-directory-custom-styles' ); + } else { + // Register and enqueue the default plugin stylesheet. + wp_register_style( + 'pmpro-member-directory-styles', + plugins_url( 'css/pmpro-member-directory.css', __FILE__ ), + array(), + PMPRO_MEMBER_DIRECTORY_VERSION + ); + wp_enqueue_style( 'pmpro-member-directory-styles' ); } - $hide_from_dir = isset( $_REQUEST['hide_directory'] ) ? sanitize_text_field( $_REQUEST['hide_directory'] ) : null; - update_user_meta( $user_id, 'pmpromd_hide_directory', $hide_from_dir ); + // Customize our styles for the WP Admin Bar. + $custom_css = '#wpadminbar #wp-admin-bar-pmpromd-edit-member .ab-item:before { content: "\f110"; top: 3px; }'; + wp_add_inline_style( 'pmpro-member-directory-styles', $custom_css ); } -add_action( 'personal_options_update', 'pmpromd_save_extra_profile_fields' ); -add_action( 'edit_user_profile_update', 'pmpromd_save_extra_profile_fields' ); -add_action( 'pmpro_personal_options_update', 'pmpromd_save_extra_profile_fields' ); +add_action( 'wp_enqueue_scripts', 'pmpromd_register_styles' ); + +/** + * TODO: Probably move some of this logic into core PMPro and then deprecate the rest of the functions in this file. + */ function pmpromd_display_file_field($meta_field) { $meta_field_file_type = wp_check_filetype($meta_field['fullurl']); switch ($meta_field_file_type['type']) { @@ -142,42 +105,6 @@ function pmpromd_display_file_field($meta_field) { } } -/** - * Filters the name to display for the member in the directory or profile page. - * - * @since 1.0 - * - * @param object $user The WP_User object for the profile. - * @param string $display_name The name to display for the user. - */ -function pmpro_member_directory_get_member_display_name( $user ) { - // Make sure we have a user. - if ( ! $user instanceof WP_User ) { - return ''; - } - - // Get their display name. - $display_name = apply_filters( 'pmpro_member_directory_display_name', $user->display_name, $user ); - - return $display_name; -} - -/* -Function to add links to the plugin row meta -*/ -function pmpromd_plugin_row_meta($links, $file) { - if(strpos($file, 'pmpro-member-directory.php') !== false) - { - $new_links = array( - '' . __( 'Docs', 'pmpro-member-directory' ) . '', - '' . __( 'Support', 'pmpro-member-directory' ) . '', - ); - $links = array_merge($links, $new_links); - } - return $links; -} -add_filter('plugin_row_meta', 'pmpromd_plugin_row_meta', 10, 2); - /** * Formatting profile fields based on the field type * @@ -256,96 +183,6 @@ function pmpromd_format_profile_field( $value, $field_name, $field_label = false return $value; } -/** - * Filters the user identifier used in permalinks - * - * @since 1.2.0 - * - * @param string $display_name The name to display for the user. - */ -function pmpromd_user_identifier() { - - /** - * Filter to change how user identifiers are presented. Choose between slug and ID - * Note: Value is case sensitive - * - * @since 1.2.0 - */ - return apply_filters( 'pmpromd_user_identifier', 'slug' ); -} - -/** - * Gets user based on their identifier - * - * @since 1.2.0 - * - * @param object The user object - */ -function pmpromd_get_user_by_identifier( $value ) { - - $user_identifier = pmpromd_user_identifier(); - - return get_user_by( $user_identifier, sanitize_text_field( $value ) ); - -} - -/** - * Gets a user from the pu URL value - * - * @since 1.2.0 - * - */ -function pmpromd_get_user( $user_id = false ){ - - global $wp_query, $current_user; - - if ( $user_id ) { - //We're specifying which user we want to display - $pu = get_user_by( 'id', intval( $user_id ) ); - } elseif ( ! empty( $wp_query->get( 'pu' ) ) ) { - //Using the new permalinks /profile/user - $pu = pmpromd_get_user_by_identifier( $wp_query->get( 'pu' ) ); - } elseif ( ! empty( $_REQUEST['pu'] ) ) { - //Using old url structure /profile/?pu=user - $pu = pmpromd_get_user_by_identifier( $_REQUEST['pu'] ); - } elseif ( ! empty( $current_user->ID ) ) { - $pu = $current_user; - } else { - $pu = false; - } - - return $pu; - -} - -/** - * Adds an edit profile link when on the Profile page - */ -function pmpromd_add_edit_profile($admin_bar){ - - global $pmpro_pages, $post, $current_user; - - if( current_user_can( 'manage_options' ) && !empty( $post ) && $pmpro_pages['profile'] == $post->ID ){ - - $pu = pmpromd_get_user(); - - if( $pu ){ - - $edit_link = get_edit_user_link( $pu->ID ); - $admin_bar->add_menu( array( - 'id' => 'pmpromd-edit-profile', - 'title' => esc_html__( 'Edit Profile', 'pmpro-member-directory' ), - 'href' => $edit_link, - 'meta' => array( - 'title' => __( 'Edit Profile', 'pmpro-member-directory' ), - ), - )); - - } - } - -} -add_action( 'admin_bar_menu', 'pmpromd_add_edit_profile', 100 ); /** * Filter the fields we are expecting to show and make sure the user has the required level. @@ -403,242 +240,3 @@ function pmpromd_filter_profile_fields_for_levels( $profile_fields, $pu ) { } add_filter( 'pmpro_member_profile_fields', 'pmpromd_filter_profile_fields_for_levels', 10, 2 ); - -/** - * We determine that the URL base is for the profile and then set up the rewrite rule - */ -function pmpromd_custom_rewrite_rules() { - - global $pmpro_pages; - - if ( empty( $pmpro_pages ) || empty( $pmpro_pages['profile'] ) ) { - return; - } - - $profile_permalink = get_the_permalink( $pmpro_pages['profile'] ); - - $base_site_url = get_site_url(); - - $profile_base = str_replace( $base_site_url . '/', '', $profile_permalink ); - - add_rewrite_rule( - $profile_base.'([^/]+)/?$', - 'index.php?pagename=' . $profile_base . '&pu=$matches[1]', - 'top' - ); - -} -add_action( 'init', 'pmpromd_custom_rewrite_rules', 10 ); - - -/** - * Adding in the ?pu parameter so that we can retrieve the value from the pretty permalink - */ -function pmpromd_custom_query_vars( $query_vars ) { - - $query_vars[] = 'pu'; - - return $query_vars; -} - -add_filter( 'query_vars', 'pmpromd_custom_query_vars', 10, 1 ); - -/** - * On Page Settings Save, Flush Rewrite Rules - */ -function pmpromd_pagesettings_flush(){ - - if( - !empty( $_REQUEST['page'] ) && - $_REQUEST['page'] == 'pmpro-pagesettings' && //Are we on the PMPro Page Settings - !empty( $_REQUEST['savesettings']) && //Are we hitting the save button - ( !empty( $_REQUEST['profile_page_id'] ) ) //Is there a profile page present - ){ - - flush_rewrite_rules( true ); - } - -} -add_action( 'admin_init', 'pmpromd_pagesettings_flush', 4 ); - -/** - * We're saving a page, is it a Profile page - */ -function pmpromd_page_save_flush( $post_id ){ - - global $pmpro_pages; - - if( !empty( $pmpro_pages['profile'] ) && - (int)$pmpro_pages['profile'] == $post_id && - did_action( 'init' ) - ) { - flush_rewrite_rules( true ); - } - -} -add_action( 'save_post', 'pmpromd_page_save_flush', 10, 1 ); - -/** - * Redirect from the OLD profile URL to the new URL's - */ -function pmpromd_redirect_profile_links(){ - - if( !empty( $_REQUEST['pu'] ) ){ - - $structure = get_option( 'permalink_structure' ); - - if( !empty( $structure ) ) { - - wp_redirect( pmpromd_build_profile_url( $_REQUEST['pu'], false, true ), 302, 'WordPress' ); - exit(); - - } - } - -} -add_action( 'init', 'pmpromd_redirect_profile_links' ); - -/** - * Build profile URL - */ -function pmpromd_build_profile_url( $pu, $profile_url = false, $separator = false ) { - - global $pmpro_pages; - - if( !empty( $pmpro_pages['profile'] ) && !$profile_url ) { - $profile_url = apply_filters( 'pmpromd_profile_url', get_permalink( $pmpro_pages['profile'] ) ); - } - - $structure = get_option( 'permalink_structure' ); - - if( is_object( $pu ) ) { - //We can't use 'slug' directly when getting the user nicename - $user_identifier = strtolower( pmpromd_user_identifier() ); - - if( $user_identifier == 'id' ) { - $pu = $pu->ID; - } else { - $pu = $pu->user_nicename; - } - } - - if( empty( $pu ) ) { - return ''; - } - - if( empty( $structure ) ) { - //We're using plain permalinks here. Query parameters to the rescue! - return add_query_arg( array( 'pu' => $pu ), $profile_url ); - } - - if( strpos( $structure, 'post_id' ) !== FALSE ) { - //Numeric permalinks don't have a trailing slash for some readon - $separator = true; - } - - if( $separator ) { - return $profile_url . '/' . sanitize_title( $pu ); - } else { - return $profile_url . sanitize_title( $pu ); - } -} - -/** - * Run an upgrade check to compare versions and flush rewrite rules - * - * @since 1.2 - * - * @return void - */ -function pmpromd_check_for_upgrade() { - - if ( ! function_exists( 'pmpro_init' ) ) { - return; - } - - $pmpromd_db_version = get_option("pmpro_md_db_version"); - - if( empty( $pmpromd_db_version ) || version_compare( $pmpromd_db_version, '1.2', '<' ) ) { - - flush_rewrite_rules( true ); - - pmpro_setOption("md_db_version", "1.2"); - - } - -} -add_action( 'admin_init', 'pmpromd_check_for_upgrade' ); - -/** - * Strip the [pmpro_member_directory] or [pmpro_member_profile] shortcode and blocks from content if the current user can't edit users. - * - * @since TBD - * - * @return mixed The content with the shortcode removed. Will be the same type as the input. - */ -function pmpromd_maybe_strip_shortcodes( $content ) { - // If the user can edit users, we don't need to strip the shortcode. - if ( current_user_can( 'edit_users' ) ) { - return $content; - } - - // If an array is passed in, filter all elements recursively. - if ( is_array( $content ) ) { - foreach ( $content as $key => $value ) { - $content[ $key ] = pmpromd_maybe_strip_shortcodes( $value ); - } - return $content; - } - - // If we're not looking at a string, just return it. - if ( ! is_string( $content ) ) { - return $content; - } - - // Okay, we have a string, figure out the regex. - $shortcodeRegex = get_shortcode_regex( array( 'pmpro_member_directory', 'pmpro_member_profile' ) ); - - // Remove various blocks. - $blockWrapperPatterns = array( - "", - "", - "//", - "//", - "/\s*$shortcodeRegex\s*/s", - "/$shortcodeRegex/" - ); - - $content = preg_replace( $blockWrapperPatterns, '', $content ); - - return $content; -} -add_filter( 'content_save_pre', 'pmpromd_maybe_strip_shortcodes' ); -add_filter( 'excerpt_save_pre', 'pmpromd_maybe_strip_shortcodes' ); -add_filter( 'widget_update_callback', 'pmpromd_maybe_strip_shortcodes' ); - -/** - * Only allow those with the edit_users capability - * to use the Directory or Profile shortcodes in post_meta. - * - * @since TBD - * @param int $meta_id ID of the meta data entry. - * @param int $object_id ID of the object the meta is attached to. - * @param string $meta_key Meta key. - * @param mixed $_meta_value Meta value. - * @return void - */ -function pmpromd_maybe_strip_shortcodes_from_post_meta( $meta_id, $object_id, $meta_key, $_meta_value ) { - // Bail if the value is not a string or array. - if ( ! is_string( $_meta_value ) && ! is_array( $_meta_value ) ) { - return; - } - - // Strip the shortcode from the meta value. - $stripped_value = pmpromd_maybe_strip_shortcodes( $_meta_value ); - - // If there was a change, save our stripped version. - if ( $stripped_value !== $_meta_value ) { - update_post_meta( $object_id, $meta_key, $stripped_value ); - } -} -add_action( 'updated_post_meta', 'pmpromd_maybe_strip_shortcodes_from_post_meta', 10, 4 ); \ No newline at end of file From f7e0727a82b534a5671b49dc6fd76b317b9487a6 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 17 Nov 2024 12:12:56 -0500 Subject: [PATCH 08/24] Initial work toward the improved profile shortcode and functions to get field display values --- includes/deprecated.php | 40 +++ includes/functions.php | 289 ++++++++++++++++- includes/search.php | 32 ++ pmpro-member-directory.php | 5 + shortcodes/search.php | 8 + templates/profile.php | 631 ++++++++++--------------------------- 6 files changed, 533 insertions(+), 472 deletions(-) create mode 100644 includes/deprecated.php create mode 100644 includes/search.php create mode 100644 shortcodes/search.php diff --git a/includes/deprecated.php b/includes/deprecated.php new file mode 100644 index 0000000..d54ee66 --- /dev/null +++ b/includes/deprecated.php @@ -0,0 +1,40 @@ + new filter name (or null if there is no alternative). + $pmpromd_map_deprecated_filters = array( + 'pmpro_member_profile_fields' => 'pmpro_member_profile_elements', + ); + + foreach ( $pmpromd_map_deprecated_filters as $old => $new ) { + if ( has_filter( $old ) ) { + if ( ! empty( $new ) ) { + // We have an alternative filter. Let's show an error message and forward to that new filter. + /* translators: 1: the old hook name, 2: the new or replacement hook name */ + trigger_error( esc_html( sprintf( esc_html__( 'The %1$s hook has been deprecated in the Member Directory Add On for Paid Memberships Pro. Please use the %2$s hook instead.', 'pmpro-member-directory' ), $old, $new ) ) ); + + // Add filters back using the new tag. + foreach( $wp_filter[$old]->callbacks as $priority => $callbacks ) { + foreach( $callbacks as $callback ) { + add_filter( $new, $callback['function'], $priority, $callback['accepted_args'] ); + } + } + } else { + // We don't have an alternative filter. Let's just show an error message. + /* translators: 1: the old hook name */ + trigger_error( esc_html( sprintf( esc_html__( 'The %1$s hook has been deprecated in Member Directory Add On for Paid Memberships Pro and may not be available in future versions.', 'pmpro-member-directory' ), $old ) ) ); + } + } + } +} +add_action( 'init', 'pmpromd_init_check_for_deprecated_filters', 99 ); diff --git a/includes/functions.php b/includes/functions.php index bc1d6ba..6e91c13 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -90,7 +90,7 @@ function pmpromd_get_user_by_identifier( $value ) { * @since 1.2.0 * */ -function pmpromd_get_user( $user_id = false ){ +function pmpromd_get_user( $user_id = false ) { global $wp_query, $current_user; if ( $user_id ) { @@ -199,3 +199,290 @@ function pmpromd_build_profile_url( $pu, $profile_url = false, $separator = fals return $profile_url . sanitize_title( $pu ); } } + +/** + * Update the_title for the Profile page. + */ +function pmpromd_the_title_profile_page( $title, $post_id = NULL ) { + global $main_post_id, $current_user, $wp_query; + if( $post_id == $main_post_id ) { + $pu = pmpromd_get_user(); + + $display_name = pmpro_member_directory_get_member_display_name( $pu ); + + if( ! empty( $display_name ) ){ + $title = $display_name; + } + } + return $title; +} +add_filter( 'the_title', 'pmpromd_the_title_profile_page', 10, 2 ); + +/** + * Update the document title parts for the Profile page. + */ +function pmpromd_document_title_parts( $title_parts ) { + global $wpdb, $main_post_id, $post, $current_user, $wp_query; + + if ( isset( $post->ID ) && $post->ID == $main_post_id ) { + + $pu = pmpromd_get_user(); + + $display_name = pmpro_member_directory_get_member_display_name( $pu ); + + if ( ! empty( $display_name ) ) { + $title_parts['title'] = $display_name; // Set the main title part. + } + } + + return $title_parts; +} +add_filter( 'document_title_parts', 'pmpromd_document_title_parts' ); + +/** + * We're working with the menu now so remove the filters. + * + * @since TBD + * + * @param string|null $output Nav menu output to short-circuit with. Default null. + * + * @return string|null Nav menu output to short-circuit with. Default null. + */ +function pmpromd_remove_title_filters_in_menus( $nav_menu ) { + // Before we work with the menu, remove the title filter. + remove_filter( 'the_title', 'pmpromd_the_title_profile_page', 10, 2 ); + + // Remove the `pmpromd_wp_title` filter. + // This is no longer used in the Add On but may be present in legacy custom templates. + remove_filter( 'wp_title', 'pmpromd_wp_title', 10, 2 ); + return $nav_menu; +} +add_filter( 'pre_wp_nav_menu', 'pmpromd_remove_title_filters_in_menus' ); + +/** + * We're done working with the menu so add those filters back. + * + * @since TBD + * + * @param string $items The HTML list content for the menu items. + * + * @return string The HTML list content for the menu items. + */ +function pmpromd_readd_title_filters_in_menus( $items ) { + // We are done working with menu, so add the title filter back. + add_filter( 'the_title', 'pmpromd_the_title_profile_page', 10, 2 ); + + // Add the `pmpromd_wp_title` filter back. + // This is no longer used in the Add On but may be present in legacy custom templates. + add_filter( 'wp_title', 'pmpromd_wp_title', 10, 2 ); + return $items; +} +add_filter( 'wp_nav_menu_items', 'pmpromd_readd_title_filters_in_menus' ); + +/** + * Preheader operations for the profile page. + * + * @since TBD + * @return void + */ +function pmpromd_profile_page_preheader() { + global $post, $pmpro_pages, $current_user; + + // Bail if we're not on the profile page. + if ( empty( $pmpro_pages['profile'] ) || ! is_page( $pmpro_pages['profile'] ) ) { + return; + } + + /** + * Preheader operations here. + */ + global $main_post_id; + $main_post_id = $post->ID; + + // Get the profile user. + $pu = pmpromd_get_user(); + + // If we are going to redirect, set the page to redirect to. + if ( ! empty( $pmpro_pages['directory'] ) ) { + $redirect = get_permalink( $pmpro_pages['directory'] ); + } else { + $redirect = home_url(); + } + + // Is this user hidden from directory? + if ( ! empty( $pu ) ) { + $pmpromd_hide_directory = get_user_meta( $pu->ID, 'pmpromd_hide_directory', true ); + } else { + $pmpromd_hide_directory = false; + } + + // If no profile user, membership level, or hidden, go to directory or home. + if ( empty( $pu ) || empty( $pu->ID ) || ! pmpro_hasMembershipLevel( null, $pu->ID ) || $pmpromd_hide_directory == '1' ) { + wp_redirect( $redirect ); + exit; + } + + // Integrate with Approvals Add On. + if ( class_exists( 'PMPro_Approvals' ) ){ + // Check that the user has a membership level that does not require approval + // or that the user has a membership level that does require approval and has been approved. + $user_levels = pmpro_getMembershipLevelsForUser( $pu->ID ); + $approval_levels = PMPro_Approvals::getApprovalLevels(); + $okay = false; + foreach ( $user_levels as $level ) { + if ( ! in_array( $level->id, $approval_levels ) || PMPro_Approvals::isApproved( $pu->ID, $level->id ) ) { + $okay = true; + break; + } + } + + if ( ! $okay ) { + wp_redirect( $redirect ); + exit; + } + } + + /** + * If a level is required for the profile page, make sure the profile user has it. + */ + + // Check to see if the page's content is restricted by shortcode, if so we don't have to redirect away. + if ( has_shortcode( $post->post_content, 'membership' ) || has_block( 'pmpro/membership', $post->post_content ) ) { + return; + } + + // Check if levels are required within the profile's shortcode. + // If they don't have that level, redirect away. + $levels = pmpro_getMatches( "/ levels?=[\"']([^\"^']*)[\"']/", $post->post_content, true ); + if ( ! empty( $levels ) && ! pmpro_hasMembershipLevel( explode( ",", $levels ), $pu->ID ) ) { + wp_redirect( $redirect ); + exit; + } +} +add_action( 'wp', 'pmpromd_profile_page_preheader', 1 ); + +/** + * Prepare the elements attribute of the shortcodes. + */ +function pmpromd_prepare_elements_array( $elements ) { + // Initialize the elements array. + $elements_array = array(); + + if ( ! empty( $elements ) ) { + // Remove a trailing comma or semicolon if it exists. + $elements = rtrim( $elements, ',;' ); + + // Explode the elements string. + $elements = explode( ';', $elements ); + foreach ( $elements as $element ) { + // Remove spaces from the beginning and end of the element. + $element = trim( $element ); + + // Check if the element is empty. + if ( empty( $element ) ) { + continue; + } + + if ( str_contains( $element, ',' ) ) { + // If there is a comma, then we know it has label/field pair. + $elements_array[] = array_map( 'trim', explode( ',', $element ) ); + } else { + // Otherwise we have just the field with no label. + $elements_array[] = array( '', trim( $element ) ); + } + } + } + + return $elements_array; +} + +/** + * Get the value of a specific element from a string of HTML. + */ +function pmpromd_get_display_value( $element, $pu ) { + // Is this a user field? + if ( class_exists( 'PMPro_Field_Group' ) ) { + $user_field = PMPro_Field_Group::get_field( $element[1] ); + } else { + $user_field = pmpro_get_user_field( $element[1] ); + } + + // Yes, this is a user field. Check that the user has the required level for this field. + if ( ! empty( $user_field ) ) { + if ( ! empty( $user_field->levels ) && ! pmpro_hasMembershipLevel( $user_field->levels, $pu->ID ) ) { + // The user does not have the required level for this field. + return ''; + } + $value = $pu->{$element[1]}; + return $user_field->displayValue( $value, false ); + } else { + // Let's try to get the value from other places and format it for return. + + // Get a list of fields related to the user's level. + $pmpro_level_fields = array( + 'membership_name', + 'membership_startdate', + 'membership_enddate', + ); + + // Get a list of fields that should be formatted as dates. + $date_fields = array( + 'membership_startdate', + 'membership_enddate', + 'user_registered', + ); + + // Check if the $element is a PMPro level field. + if ( in_array( $element, $pmpro_level_fields ) ) { + $pu->membership_level = pmpro_getMembershipLevelForUser( $pu->ID ); + $allmylevels = pmpro_getMembershipLevelsForUser( $pu->ID ); + $membership_levels = array(); + foreach ( $allmylevels as $curlevel ) { + $membership_levels[] = $curlevel->name; + } + $pu->membership_levels = implode(', ', $membership_levels); + } + + // Additional formatting and special cases. + switch ( $element ) { + case 'display_name': + $value = '

' . pmpro_member_directory_get_member_display_name( $pu ) . '

'; + break; + case 'avatar': + /** + * Filter the size of the avatar displayed in the member directory. + * + * @since TBD + * @param int $avatar_size The size of the avatar in pixels. + * @param string $page The page where the avatar is being displayed. + * + * @return int The size of the avatar in pixels. + */ + $avatar_size = apply_filters( 'pmpro_member_directory_avatar_size', 128, $page ); + $value = get_avatar( $pu->ID, $avatar_size, NULL, $pu->display_name ); + break; + case 'membership_name': + $value = $pu->membership_levels; + break; + case 'membership_startdate': + $value = $pu->membership_level->startdate; + break; + case 'membership_enddate': + $value = $pu->membership_level->enddate; + break; + } + + // If we still do not have a value, try usermeta. + if ( empty( $value ) ) { + $value = $pu->$element; + } + + // Format the date fields. + if ( in_array( $element, $date_fields ) && ! empty( $value ) ) { + $value = date_i18n( get_option('date_format'), $value ); + } + + } + + return $value; +} diff --git a/includes/search.php b/includes/search.php new file mode 100644 index 0000000..2d77284 --- /dev/null +++ b/includes/search.php @@ -0,0 +1,32 @@ + +
+ +
+ ID; - - $pu = pmpromd_get_user(); - - // Is this user hidden from directory? - if ( ! empty( $pu ) ) { - $pmpromd_hide_directory = get_user_meta( $pu->ID, 'pmpromd_hide_directory', true ); - } else { - $pmpromd_hide_directory = false; - } - - // If no profile user, membership level, or hidden, go to directory or home. - if(empty($pu) || empty($pu->ID) || !pmpro_hasMembershipLevel(null, $pu->ID) || $pmpromd_hide_directory == '1' ) { - if(!empty($pmpro_pages['directory'])) - wp_redirect(get_permalink($pmpro_pages['directory'])); - else - wp_redirect(home_url()); - exit; - } - - // Integrate with Approvals. - if ( class_exists( 'PMPro_Approvals' ) ){ - // Check that either the user has a membership level that does not require approval - // or that the user has a membership level that does require approval and has been approved. - $user_levels = pmpro_getMembershipLevelsForUser( $pu->ID ); - $approval_levels = PMPro_Approvals::getApprovalLevels(); - $okay = false; - foreach ( $user_levels as $level ) { - if ( ! in_array( $level->id, $approval_levels ) || PMPro_Approvals::isApproved( $pu->ID, $level->id ) ) { - $okay = true; - break; - } - } - - if ( ! $okay ) { - if ( ! empty( $pmpro_pages['directory'] ) ) { - wp_redirect( get_permalink( $pmpro_pages['directory'] ) ); - } else { - wp_redirect(home_url()); - exit; - } - } - } - - /* - If a level is required for the profile page, make sure the profile user has it. - */ - - // Check to see if the page's content is restricted by shortcode, if so we don't have to redirect away. - if ( has_shortcode( $post->post_content, 'membership' ) || has_block( 'pmpro/membership', $post->post_content ) ) { - return; - } - - //check is levels are required within the profile's shortcode, if they don't have that level redirect away. - $levels = pmpro_getMatches("/ levels?=[\"']([^\"^']*)[\"']/", $post->post_content, true); - if(!empty($levels) && !pmpro_hasMembershipLevel(explode(",", $levels), $pu->ID)) - { - if(!empty($pmpro_pages['directory'])) - wp_redirect(get_permalink($pmpro_pages['directory'])); - else - wp_redirect(home_url()); - exit; - } -} -add_action("wp", "pmpromd_profile_preheader", 1); - -/* - Update the head title and H1 -*/ -function pmpromd_the_title($title, $post_id = NULL) -{ - global $main_post_id, $current_user, $wp_query; - if( $post_id == $main_post_id ) { - $pu = pmpromd_get_user(); - - $display_name = pmpro_member_directory_get_member_display_name( $pu ); - - if( !empty( $display_name ) ){ - $title = $display_name; - } - } - return $title; -} -add_filter("the_title", "pmpromd_the_title", 10, 2); - -function pmpromd_wp_title($title, $sep) -{ - global $wpdb, $main_post_id, $post, $current_user, $wp_query; - if( $post->ID == $main_post_id ) { - - $pu = pmpromd_get_user(); - - $display_name = pmpro_member_directory_get_member_display_name( $pu ); - - if( !empty( $display_name ) ) { - $title = $display_name . ' ' . $sep . ' '; - } - - $title .= get_bloginfo( 'name' ); - } - return $title; -} -add_filter("wp_title", "pmpromd_wp_title", 10, 2); - -/** - * We're working with the menu now so remove the filters. - * - * @since TBD - * - * @param string|null $output Nav menu output to short-circuit with. Default null. - * - * @return string|null Nav menu output to short-circuit with. Default null. - */ -function pmpromd_remove_filters_menu_title( $nav_menu ) { - - remove_filter( 'wp_title', 'pmpromd_wp_title', 10, 2 ); - remove_filter( 'the_title', 'pmpromd_the_title', 10, 2 ); - return $nav_menu; -} -add_filter( 'pre_wp_nav_menu', 'pmpromd_remove_filters_menu_title' ); - - /** - * We're done working with the menu so add those filters back. - * - * @since TBD - * - * @param string $items The HTML list content for the menu items. - * - * @return string The HTML list content for the menu items. + * Show the content for the [pmpro_member_profile] shortcode. */ -function pmpromd_readd_filters_menu_title( $items ) { - - // we are done working with menu, so add the title filter back - add_filter( 'wp_title', 'pmpromd_wp_title', 10, 2 ); - add_filter( 'the_title', 'pmpromd_the_title', 10, 2 ); - return $items; -} -add_filter( 'wp_nav_menu_items', 'pmpromd_readd_filters_menu_title' ); - -function pmpromd_profile_shortcode($atts, $content=null, $code="") -{ - // $atts ::= array of attributes - // $content ::= text within enclosing form of shortcode element - // $code ::= the shortcode found, when == callback name - // examples: [pmpro_member_profile avatar="false" email="false"] - +function pmpromd_profile_shortcode( $atts, $content=null, $code="" ) { extract(shortcode_atts(array( 'avatar_size' => '128', + 'elements' => NULL, 'fields' => NULL, 'show_avatar' => true, 'show_bio' => true, @@ -177,343 +19,190 @@ function pmpromd_profile_shortcode($atts, $content=null, $code="") 'user_id' => NULL ), $atts)); - global $current_user, $display_name, $wpdb, $pmpro_pages, $pmprorh_registration_fields, $wp_query; - - //some page vars - if(!empty($pmpro_pages['directory'])) - $directory_url = get_permalink($pmpro_pages['directory']); - else - $directory_url = ""; - if(!empty($pmpro_pages['profile'])) - $profile_url = get_permalink($pmpro_pages['profile']); - - //turn 0's into falses - if($show_avatar === "0" || $show_avatar === "false" || $show_avatar === "no" || $show_avatar === false ) - $show_avatar = false; - else - $show_avatar = true; - - if($show_billing === "0" || $show_billing === "false" || $show_billing === "no" || $show_billing === false ) - $show_billing = false; - else - $show_billing = true; - - if($show_bio === "0" || $show_bio === "false" || $show_bio === "no" || $show_bio === false ) - $show_bio = false; - else - $show_bio = true; - - if($show_email === "0" || $show_email === "false" || $show_email === "no" || $show_email === false ) - $show_email = false; - else - $show_email = true; - - if($show_level === "0" || $show_level === "false" || $show_level === "no" || $show_level === false ) - $show_level = false; - else - $show_level = true; + global $current_user, $pmpro_pages; - if($show_name === "0" || $show_name === "false" || $show_name === "no" || $show_name === false ) - $show_name = false; - else - $show_name = true; + // Get the directory and profile page URLs. + $directory_url = ! empty( $pmpro_pages['directory'] ) ? get_permalink( $pmpro_pages['directory'] ) : ''; + $profile_url = ! empty( $pmpro_pages['profile'] ) ? get_permalink( $pmpro_pages['profile'] ) : ''; - if($show_phone === "0" || $show_phone === "false" || $show_phone === "no" || $show_phone === false ) - $show_phone = false; - else - $show_phone = true; + // Get the user for this profile. + $pu = pmpromd_get_user( $user_id ); - if($show_search === "0" || $show_search === "false" || $show_search === "no" || $show_search === false ) - $show_search = false; - else - $show_search = true; + // Validate boolean variables. + $show_avatar = filter_var( $show_avatar, FILTER_VALIDATE_BOOLEAN ); + $show_billing = filter_var( $show_billing, FILTER_VALIDATE_BOOLEAN ); + $show_bio = filter_var( $show_bio, FILTER_VALIDATE_BOOLEAN ); + $show_email = filter_var( $show_email, FILTER_VALIDATE_BOOLEAN ); + $show_level = filter_var( $show_level, FILTER_VALIDATE_BOOLEAN ); + $show_name = filter_var( $show_name, FILTER_VALIDATE_BOOLEAN ); + $show_phone = filter_var( $show_phone, FILTER_VALIDATE_BOOLEAN ); + $show_search = filter_var( $show_search, FILTER_VALIDATE_BOOLEAN ); + $show_startdate = filter_var( $show_startdate, FILTER_VALIDATE_BOOLEAN ); + + // Build our elements array. If we have an elements attribute on the shortcode, use that and ignore any other legacy attributes. + if ( ! empty( $elements ) ) { + $elements_array = pmpromd_prepare_elements_array( $elements ); + } else { + // We need to support the legacy attributes for backwards compatibility. + $elements = ''; + if ( ! empty( $show_name ) ) { + $elements .= 'display_name;'; + } + if ( ! empty( $show_avatar ) ) { + if ( ! empty( $avatar_size ) ) { + $elements .= 'avatar|' . $avatar_size . ';'; + } else { + $elements .= 'avatar;'; + } + } + if ( ! empty( $show_bio ) ) { + $elements .= __( 'Biographical Info', 'pmpro-member-directory' ) . ',description;'; + } + if ( ! empty( $show_email ) ) { + $elements .= __( 'Email Address', 'pmpro-member-directory' ) . ', user_email;'; + } + // These are the fields that are not part of the user object and need special handling. + if ( ! empty( $show_level ) ) { + $elements .= __( 'Level', 'pmpro-member-directory' ) . ',membership_name;'; + } + if ( ! empty( $show_startdate ) ) { + $elements .= __( 'Start Date', 'pmpro-member-directory' ) . ',membership_startdate;'; + } + if ( ! empty( $show_billing ) ) { + $elements .= __( 'Address', 'pmpro-member-directory' ) . ',pmpro_baddress1|pmpro_baddress2|pmpro_bcity|pmpro_bstate|pmpro_bzipcode|pmpro_bcountry;'; + } + if ( ! empty( $show_phone ) ) { + $elements .= __( 'Phone Number', 'pmpro-member-directory' ) . ',pmpro_bphone;'; + } + if ( ! empty( $fields ) ) { + $elements .= $fields; + } + $elements_array = pmpromd_prepare_elements_array( $elements ); + } - if($show_startdate === "0" || $show_startdate === "false" || $show_startdate === "no" || $show_startdate === false ) - $show_startdate = false; - else - $show_startdate = true; + /** + * Filter the elements array for the member profile. + * + * @since TBD + * @param array $elements_array The array of elements to display on the member profile. + * @param object $pu The user object. + * @return array $elements_array The array of elements to display on the member profile. + */ + $elements_array = apply_filters( 'pmpro_member_profile_elements', $elements_array, $pu ); if(isset($_REQUEST['limit'])) $limit = intval($_REQUEST['limit']); elseif(empty($limit)) $limit = 15; - $pu = pmpromd_get_user( $user_id ); - - if ( ! empty( $pu ) ) { - $pu->membership_level = pmpro_getMembershipLevelForUser( $pu->ID ); - $allmylevels = pmpro_getMembershipLevelsForUser( $pu->ID ); - $membership_levels = array(); - foreach ( $allmylevels as $curlevel ) { - $membership_levels[] = $curlevel->name; - } - $pu->membership_levels = implode(', ', $membership_levels); - } - ob_start(); ?>
- - - - if ( ! empty( $fields_array ) ) { - for( $i = 0; $i < count($fields_array); $i++ ) { - $fields_array[$i] = explode( ',', $fields_array[$i] ); - } - } - } - else { - $fields_array = false; - } + - // Get Register Helper field options - $rh_fields = array(); - if(!empty($pmprorh_registration_fields)) { - foreach($pmprorh_registration_fields as $location) { - foreach($location as $field) { - if(!empty($field->options)){ - $rh_fields[$field->name] = $field->options; - } - } - } - } - ?> -
+
- + - display_name ) ) { - $heading_classes = array(); - $heading_classes[] = 'pmpro_card_title'; - $heading_classes[] = 'pmpro_font-x-large'; - if ( ! empty( $show_avatar ) ) { - $heading_classes[] = 'pmpro_heading-with-avatar'; - } - $heading_classes = implode( ' ', $heading_classes ); - ?> -

- - ID, $avatar_size, NULL, $pu->display_name, array("class"=>"alignright")); ?> - - -

- -
- ID, $avatar_size, NULL, $pu->display_name, array("class"=>"alignright")); ?> -
- -
- description) ) { ?> -
- - description; ?> -
- - -
- - user_email, 'user_email' ); ?> -
- - -
- - membership_levels ) ? $pu->membership_levels : ''; ?> -
- - -
- - startdate < $min_startdate ) { - $min_startdate = $level->startdate; - } - } - echo ! empty( $min_startdate ) ? date_i18n( get_option( 'date_format' ), $min_startdate ) : ''; - ?> -
- - pmpro_baddress1)) { ?> -
- - pmpro_baddress1; ?>
- pmpro_baddress2)) - echo $pu->pmpro_baddress2 . "
"; - ?> - pmpro_bcity && $pu->pmpro_bstate) { ?> - pmpro_bcity; ?>, pmpro_bstate; ?> pmpro_bzipcode; ?>
- pmpro_bcountry; ?>
+
+ +
+ +
+ +
-
- - pmpro_bphone)) { ?> -
- - pmpro_bphone); ?> -
- - $field_val; - - // If using PMPro 2.10, try use User Field function to display labels. - if ( function_exists( 'pmpro_get_label_for_user_field_value' ) && ! empty( $field_val ) && ! empty( $meta_field ) ) { - $meta_field = pmpro_get_label_for_user_field_value( $field_val, $meta_field ); - } - - if(!empty($meta_field)) - { - ?> -
- - - - $value) - $meta_field[$key] = $rh_fields[$field[1]][$value]; - } - ?> - - - - - - - - - - -
- - -
-
- "> + +
+
+ - if ( ! empty( $directory_url ) ) { - $pmpro_member_profile_action_links['view-directory'] = sprintf( '%s', esc_url( $directory_url ), esc_html__( 'View All Members', 'pmpro-member-directory' ) ); - } + +
+
+ ID === $current_user->ID ) { - // User viewing their own profile. Show an edit profile link if 'Member Profile Edit Page' is set or dashboard access is allowed. - if ( ! empty( get_option( 'pmpro_member_profile_edit_page_id' ) ) ) { - $edit_profile_url = pmpro_url( 'member_profile_edit' ); - } elseif ( ! pmpro_block_dashboard() ) { - $edit_profile_url = admin_url( 'profile.php' ); - } + if ( ! empty( $directory_url ) ) { + $pmpro_member_profile_action_links['view-directory'] = sprintf( '%s', esc_url( $directory_url ), esc_html__( 'View All Members', 'pmpro-member-directory' ) ); + } - if ( ! empty( $edit_profile_url) ) { - $pmpro_member_profile_action_links['edit-profile'] = sprintf( '%s', esc_url( $edit_profile_url ), esc_html__( 'Edit Profile', 'paid-memberships-pro' ) ); - } - } + if ( ! empty( $pu ) && $pu->ID === $current_user->ID ) { + // User viewing their own profile. Show an edit profile link if 'Member Profile Edit Page' is set or dashboard access is allowed. + if ( ! empty( get_option( 'pmpro_member_profile_edit_page_id' ) ) ) { + $edit_profile_url = pmpro_url( 'member_profile_edit' ); + } elseif ( ! pmpro_block_dashboard() ) { + $edit_profile_url = admin_url( 'profile.php' ); + } - /** - * Filter which links are displayed on the single Member Directory Profile page. - * - * @since 1.0 - * - * @param array $pmpro_member_profile_action_links Can be view-directory, edit-profile, or or custom. - * - * @return array $pmpro_member_profile_action_links - */ - $pmpro_member_profile_action_links = apply_filters( 'pmpromd_member_profile_action_links', $pmpro_member_profile_action_links ); + if ( ! empty( $edit_profile_url) ) { + $pmpro_member_profile_action_links['edit-profile'] = sprintf( '%s', esc_url( $edit_profile_url ), esc_html__( 'Edit Profile', 'paid-memberships-pro' ) ); + } + } - $allowed_html = array( - 'a' => array ( - 'class' => array(), - 'href' => array(), - 'id' => array(), - 'target' => array(), - 'title' => array(), - ), - ); - echo wp_kses( implode( pmpro_actions_nav_separator(), $pmpro_member_profile_action_links ), $allowed_html ); - ?> -
-
- + /** + * Filter which links are displayed on the single Member Directory Profile page. + * + * @since 1.0 + * + * @param array $pmpro_member_profile_action_links Can be view-directory, edit-profile, or or custom. + * + * @return array $pmpro_member_profile_action_links + */ + $pmpro_member_profile_action_links = apply_filters( 'pmpromd_member_profile_action_links', $pmpro_member_profile_action_links ); + + $allowed_html = array( + 'a' => array ( + 'class' => array(), + 'href' => array(), + 'id' => array(), + 'target' => array(), + 'title' => array(), + ), + ); + echo wp_kses( implode( pmpro_actions_nav_separator(), $pmpro_member_profile_action_links ), $allowed_html ); + ?> +
+
Date: Sun, 17 Nov 2024 12:45:10 -0500 Subject: [PATCH 09/24] Fixing avatar size logic and removing a filter that we do not need --- includes/functions.php | 17 +++++++---------- templates/profile.php | 9 ++++----- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index 6e91c13..8f0f222 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -443,22 +443,19 @@ function pmpromd_get_display_value( $element, $pu ) { $pu->membership_levels = implode(', ', $membership_levels); } + // Get the avatar_size for the avatar element. + if ( str_contains( $element, 'avatar' ) ) { + $element_parts = explode( '|', $element ); + $element = $element_parts[0]; + $avatar_size = ! empty( $element_parts[1] ) ? $element_parts[1] : 128; + } + // Additional formatting and special cases. switch ( $element ) { case 'display_name': $value = '

' . pmpro_member_directory_get_member_display_name( $pu ) . '

'; break; case 'avatar': - /** - * Filter the size of the avatar displayed in the member directory. - * - * @since TBD - * @param int $avatar_size The size of the avatar in pixels. - * @param string $page The page where the avatar is being displayed. - * - * @return int The size of the avatar in pixels. - */ - $avatar_size = apply_filters( 'pmpro_member_directory_avatar_size', 128, $page ); $value = get_avatar( $pu->ID, $avatar_size, NULL, $pu->display_name ); break; case 'membership_name': diff --git a/templates/profile.php b/templates/profile.php index 6f5b422..6eeae5d 100644 --- a/templates/profile.php +++ b/templates/profile.php @@ -39,6 +39,9 @@ function pmpromd_profile_shortcode( $atts, $content=null, $code="" ) { $show_search = filter_var( $show_search, FILTER_VALIDATE_BOOLEAN ); $show_startdate = filter_var( $show_startdate, FILTER_VALIDATE_BOOLEAN ); + // Validate the avatar size. + $avatar_size = intval( $avatar_size ); + // Build our elements array. If we have an elements attribute on the shortcode, use that and ignore any other legacy attributes. if ( ! empty( $elements ) ) { $elements_array = pmpromd_prepare_elements_array( $elements ); @@ -49,11 +52,7 @@ function pmpromd_profile_shortcode( $atts, $content=null, $code="" ) { $elements .= 'display_name;'; } if ( ! empty( $show_avatar ) ) { - if ( ! empty( $avatar_size ) ) { - $elements .= 'avatar|' . $avatar_size . ';'; - } else { - $elements .= 'avatar;'; - } + $elements .= 'avatar|' . $avatar_size . ';'; } if ( ! empty( $show_bio ) ) { $elements .= __( 'Biographical Info', 'pmpro-member-directory' ) . ',description;'; From db46cb205113f060452aefdfd31484306df5dfdb Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 17 Nov 2024 13:17:33 -0500 Subject: [PATCH 10/24] Fixing lost heading --- templates/directory.php | 749 ++++++++++++++++++++-------------------- 1 file changed, 374 insertions(+), 375 deletions(-) diff --git a/templates/directory.php b/templates/directory.php index 86432e0..3a469b5 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -181,416 +181,414 @@ function pmpromd_shortcode($atts, $content=null, $code="")
- 0) { ?> - - () - - - - -

- %s.', 'pmpro-member-directory' ), stripslashes( ucwords( esc_html( $s ) ) ) ) ); - // If there is a directory URL, display a link to view all members. - if ( ! empty( $directory_url ) ) { - ?> - - -

+

+ + + %s.','pmpro-member-directory'), stripslashes( ucwords(esc_html($s)))); ?> + + + + + 0) { ?> + + () + + +

+
+ %s.', 'pmpro-member-directory' ), stripslashes( ucwords( esc_html( $s ) ) ) ) ); - if ( ! empty( $fields ) ) { - // Check to see if the Block Editor is used or the shortcode. - if ( strpos( $fields, "\n" ) !== FALSE ) { - $fields = rtrim( $fields, "\n" ); // clear up a stray \n - $fields_array = explode("\n", $fields); // For new block editor. - } else { - $fields = rtrim( $fields, ';' ); // clear up a stray ; - $fields_array = explode(";",$fields); + // If there is a directory URL, display a link to view all members. + if ( ! empty( $directory_url ) ) { + ?> + + +
+ options ) ) { - $rh_fields[$field->name] = $field->options; + if ( ! empty( $fields_array ) ) { + for ( $i = 0; $i < count( $fields_array ); $i++ ) { + $fields_array[$i] = explode( ",", trim( $fields_array[$i] ) ); } } + } else { + $fields_array = false; } - } - ?> - $avatar_size, - 'fields' => $fields, - 'layout' => $layout, - 'level' => $level, - 'levels' => $levels, - 'limit' => $limit, - 'link' => $link, - 'order_by' => $order_by, - 'order' => $order, - 'show_avatar' => $show_avatar, - 'show_email' => $show_email, - 'show_level' => $show_level, - 'show_search' => $show_search, - 'show_startdate' => $show_startdate, - 'avatar_align' => $avatar_align, - 'fields_array' => $fields_array - ) ); - - do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); ?> - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - options ) ) { + $rh_fields[$field->name] = $field->options; + } + } + } } + ?> - // Loop through the users and ouptut the content. - $count = 0; - $data_wrapper = ( $layout == 'table' ) ? 'td' : 'p'; - foreach($theusers as $auser) { - $auser = get_userdata($auser->ID); - $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); - $user_fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); - $count++; - - // Show the header for the user. - if ( $layout == 'table' ) { - ?> - "> - $avatar_size, + 'fields' => $fields, + 'layout' => $layout, + 'level' => $level, + 'levels' => $levels, + 'limit' => $limit, + 'link' => $link, + 'order_by' => $order_by, + 'order' => $order, + 'show_avatar' => $show_avatar, + 'show_email' => $show_email, + 'show_level' => $show_level, + 'show_search' => $show_search, + 'show_startdate' => $show_startdate, + 'avatar_align' => $avatar_align, + 'fields_array' => $fields_array + ) ); + + do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); ?> + +
+ -
+
- "> +
+ + + + + + + + + + + + + + + + + + + + + + ID); + $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); + $user_fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); + $count++; + + // Show the header for the user. if ( $layout == 'table' ) { ?> - + "> -
- - ID, $avatar_size, NULL, $auser->display_name); ?> - - ID, $avatar_size, NULL, $auser->display_name); ?> - -
+
+
- < class="pmpro_member_directory_email"> - + + - +
+ + ID, $avatar_size, NULL, $auser->display_name); ?> + + ID, $avatar_size, NULL, $auser->display_name); ?> + +
user_email, 'user_email' ); - ?> - > - + < class="pmpro_member_directory_email"> + + user_email, 'user_email' ); + ?> + > + ID ); - $membership_levels = array(); - if ( ! isset( $levels ) ) { - // Show all the user's levels. - foreach ( $alluserlevels as $curlevel ) { - $membership_levels[] = $curlevel->name; + // Show the user's membership level. + if ( ! empty( $show_level ) ) { + ?> + < class="pmpro_member_directory_level"> + + + id, $levels_array) ) { + + $alluserlevels = pmpro_getMembershipLevelsForUser( $auser->ID ); + $membership_levels = array(); + if ( ! isset( $levels ) ) { + // Show all the user's levels. + foreach ( $alluserlevels as $curlevel ) { $membership_levels[] = $curlevel->name; } + } else { + $levels_array = explode(',', $levels); + // Show only the levels included in the directory. + foreach ( $alluserlevels as $curlevel ) { + if ( in_array( $curlevel->id, $levels_array) ) { + $membership_levels[] = $curlevel->name; + } + } } - } - $auser->membership_levels = implode( ', ', $membership_levels ); - echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; - ?> - > - - < class="pmpro_member_directory_date"> - membership_levels = implode( ', ', $membership_levels ); + echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; ?> - + > + + < class="pmpro_member_directory_date"> startdate < $min_startdate ) { - $min_startdate = $level->startdate; + // If the layout is not a table, print "Start Date" as a label. + if ( $layout !== 'table' ) { + ?> + + - > - + < class="pmpro_member_directory_link"> + + > + - < class="pmpro_member_directory_link"> - - > - + + + + + - - + +
- - - - - - - - - - - - - -
+ + + + + + + + + + + + + +
- - ID, $avatar_size, NULL, $auser->user_nicename ); ?> - - ID, $avatar_size, NULL, $auser->user_nicename ); ?> - -
-

- - - - - -

-
+ + ID, $avatar_size, NULL, $auser->user_nicename ); ?> + + ID, $avatar_size, NULL, $auser->user_nicename ); ?> + + - < class="pmpro_member_directory_level"> - - +

+ + + + + +

+
startdate < $min_startdate ) { + $min_startdate = $level->startdate; + } + } + echo ! empty( $min_startdate ) ? date_i18n( get_option( 'date_format' ), $min_startdate ) : ''; + ?> + > + {$field[1]}; - if ( ! empty( $meta_field ) ) { - ?> -

- - - + foreach( $user_fields_array as $field ) { + // Fix for a trailing space in the 'fields' shortcode attribute. + if ( $field[0] === '' ) { + break; + } + + $meta_field = $auser->{$field[1]}; + if ( ! empty( $meta_field ) ) { + ?> +

$value) { - $meta_field[$key] = $rh_fields[$field[1]][$value]; + if ( is_array( $meta_field ) && ! empty( $meta_field['filename'] ) ) { + // This is a file field. + ?> + + + $value) { + $meta_field[$key] = $rh_fields[$field[1]][$value]; + } } + ?> + + + + + + + + {$field[1]}, $field[1] ); } ?> - - - - - - - - {$field[1]}, $field[1] ); - } - ?> -

- +
- - -
-
- - - -
+
1 ) { - $query_args = array( - 'ps' => $s, - 'pn' => $pn-1, - 'limit' => $limit, - ); - $query_args = apply_filters( 'pmpromd_pagination_url', $query_args, 'prev' ); - ?> - « - +
- - ID ) ) ) . '" title="' . esc_attr__( 'Previous', 'pmpromd' ) . '">...'; - } - - if( round( $number_of_pages, 0 ) !== 1 && $pn !== 1 ) { - //If there's only one page, no need to show the page numbers - for( $i = $pn; $i <= $number_of_pages; $i++ ){ - if( $counter <= 6 ){ - $query_args = array( - 'ps' => $s, - 'pn' => $i, - 'limit' => $limit, - ); - - if( $i == $pn ){ $active_class = 'class="pmpro_page_active"'; } else { $active_class = ''; } - - echo '' . $i . ''; + + ID ) ) ) . '" title="' . esc_attr__( 'Previous', 'pmpromd' ) . '">...'; } - $counter++; - } - } - ?> - + + if ( round( $number_of_pages, 0 ) !== 1 && $pn !== 1 ) { + //If there's only one page, no need to show the page numbers + for( $i = $pn; $i <= $number_of_pages; $i++ ){ + if( $counter <= 6 ){ + $query_args = array( + 'ps' => $s, + 'pn' => $i, + 'limit' => $limit, + ); + + if( $i == $pn ){ $active_class = 'class="pmpro_page_active"'; } else { $active_class = ''; } + + echo '' . $i . ''; + } + $counter++; + } + } + ?> + + $end ) { From 3573c88f1016c299b8aeb479c0eeef069f77e3eb Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 17 Nov 2024 13:30:58 -0500 Subject: [PATCH 11/24] Fixing search form not to wrap in pmpro class unless used as standalone shortcode --- includes/search.php | 26 ++++++++++++-------------- shortcodes/search.php | 11 ++++++++++- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/includes/search.php b/includes/search.php index 2d77284..83ad5c1 100644 --- a/includes/search.php +++ b/includes/search.php @@ -14,19 +14,17 @@ function pmpromd_search_form() { // Get the limit for the search results. $limit = ! empty( $_REQUEST['limit'] ) ? intval( $_REQUEST['limit'] ) : 10; ?> -
- -
+ +
+ +
+ Date: Sun, 17 Nov 2024 13:32:48 -0500 Subject: [PATCH 12/24] Do not filter the_title if we are in the admin --- includes/functions.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/includes/functions.php b/includes/functions.php index 8f0f222..c620165 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -204,6 +204,11 @@ function pmpromd_build_profile_url( $pu, $profile_url = false, $separator = fals * Update the_title for the Profile page. */ function pmpromd_the_title_profile_page( $title, $post_id = NULL ) { + // If we're in the admin, don't do anything. + if ( is_admin() ) { + return $title; + } + global $main_post_id, $current_user, $wp_query; if( $post_id == $main_post_id ) { $pu = pmpromd_get_user(); From e5993779d40b7ffbed0398279715bbb779576aab Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 17 Nov 2024 14:33:54 -0500 Subject: [PATCH 13/24] Verifying there is a permalink structure before adding a rewrite rule --- includes/functions.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/includes/functions.php b/includes/functions.php index bc1d6ba..2ab54f0 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -121,6 +121,11 @@ function pmpromd_custom_rewrite_rules() { return; } + $structure = get_option( 'permalink_structure' ); + if ( empty( $structure ) ) { + return; + } + $profile_permalink = get_the_permalink( $pmpro_pages['profile'] ); $base_site_url = get_site_url(); $profile_base = str_replace( $base_site_url . '/', '', $profile_permalink ); From d9f67d7905a1c45c23a7ad3f85f1439af2c87780 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 17 Nov 2024 15:35:42 -0500 Subject: [PATCH 14/24] Cleaning up line breaks in the fields array that the block editor versions use --- includes/functions.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/includes/functions.php b/includes/functions.php index c620165..eb7aacf 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -377,7 +377,12 @@ function pmpromd_prepare_elements_array( $elements ) { // Remove a trailing comma or semicolon if it exists. $elements = rtrim( $elements, ',;' ); - // Explode the elements string. + // Convert line breaks to semicolons (for the block editor). + if ( strpos( $elements, "\n" ) !== FALSE ) { + $elements = str_replace( "\n", ';', $elements ); + } + + // Build the elements array. $elements = explode( ';', $elements ); foreach ( $elements as $element ) { // Remove spaces from the beginning and end of the element. From 7489a2f718d33fe7415b5ebdb7097d681bb61d45 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 17 Nov 2024 16:33:55 -0500 Subject: [PATCH 15/24] Deprecating the pmpro_member_directory_fields filter --- includes/deprecated.php | 1 + templates/profile.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/includes/deprecated.php b/includes/deprecated.php index d54ee66..0bff9da 100644 --- a/includes/deprecated.php +++ b/includes/deprecated.php @@ -14,6 +14,7 @@ function pmpromd_init_check_for_deprecated_filters() { // Deprecated filter name => new filter name (or null if there is no alternative). $pmpromd_map_deprecated_filters = array( 'pmpro_member_profile_fields' => 'pmpro_member_profile_elements', + 'pmpro_member_directory_fields' => 'pmpro_member_directory_elements', ); foreach ( $pmpromd_map_deprecated_filters as $old => $new ) { diff --git a/templates/profile.php b/templates/profile.php index 6eeae5d..29dd8d6 100644 --- a/templates/profile.php +++ b/templates/profile.php @@ -123,7 +123,7 @@ function pmpromd_profile_shortcode( $atts, $content=null, $code="" ) {
From a1bef517a30fde3798cf218132f5a00709a038bb Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 17 Nov 2024 16:34:12 -0500 Subject: [PATCH 16/24] Adding a location parameter to format values differently based on if this is the profile or directory page --- includes/functions.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index eb7aacf..5e99f6e 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -409,7 +409,7 @@ function pmpromd_prepare_elements_array( $elements ) { /** * Get the value of a specific element from a string of HTML. */ -function pmpromd_get_display_value( $element, $pu ) { +function pmpromd_get_display_value( $element, $pu, $location = 'profile' ) { // Is this a user field? if ( class_exists( 'PMPro_Field_Group' ) ) { $user_field = PMPro_Field_Group::get_field( $element[1] ); @@ -463,7 +463,10 @@ function pmpromd_get_display_value( $element, $pu ) { // Additional formatting and special cases. switch ( $element ) { case 'display_name': - $value = '

' . pmpro_member_directory_get_member_display_name( $pu ) . '

'; + $value = pmpro_member_directory_get_member_display_name( $pu ); + if ( $location == 'profile' ) { + $value = '

' . $value . '

'; + } break; case 'avatar': $value = get_avatar( $pu->ID, $avatar_size, NULL, $pu->display_name ); From 54f2adf35eb4ddfa70ad414dd6c4216ccc0b83c6 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 17 Nov 2024 16:41:36 -0500 Subject: [PATCH 17/24] Directory template using the same logic as the profile now --- templates/directory.php | 569 ++++++++++++---------------------------- 1 file changed, 171 insertions(+), 398 deletions(-) diff --git a/templates/directory.php b/templates/directory.php index 3a469b5..4ddd869 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -1,16 +1,11 @@ '64', + 'avatar_size' => '128', + 'elements' => NULL, 'fields' => NULL, 'layout' => 'div', 'level' => NULL, @@ -27,76 +22,42 @@ function pmpromd_shortcode($atts, $content=null, $code="") 'avatar_align' => NULL ), $atts, "pmpro_member_directory")); - global $wpdb, $post, $pmpro_pages, $pmprorh_registration_fields; + global $wpdb, $post, $pmpro_pages; - //some page vars - if(!empty($pmpro_pages['directory'])) { - $directory_url = get_permalink($pmpro_pages['directory']); - } + // Get the directory and profile page URLs. + $directory_url = ! empty( $pmpro_pages['directory'] ) ? get_permalink( $pmpro_pages['directory'] ) : ''; + $profile_url = ! empty( $pmpro_pages['profile'] ) ? get_permalink( $pmpro_pages['profile'] ) : ''; - if(!empty($pmpro_pages['profile'])) { - $profile_url = apply_filters( 'pmpromd_profile_url', get_permalink( $pmpro_pages['profile'] ) ); - } + // Validate boolean variables. + $link = filter_var( $link, FILTER_VALIDATE_BOOLEAN ); + $show_avatar = filter_var( $show_avatar, FILTER_VALIDATE_BOOLEAN ); + $show_email = filter_var( $show_email, FILTER_VALIDATE_BOOLEAN ); + $show_level = filter_var( $show_level, FILTER_VALIDATE_BOOLEAN ); + $show_search = filter_var( $show_search, FILTER_VALIDATE_BOOLEAN ); + $show_startdate = filter_var( $show_startdate, FILTER_VALIDATE_BOOLEAN ); - //turn 0's into falses - if($link === "0" || $link === "false" || $link === "no" || $link === false) - $link = false; - else - $link = true; + // Validate the avatar size. + $avatar_size = intval( $avatar_size ); - //did they use level instead of levels? - if(empty($levels) && !empty($level)) + // Did they use level instead of levels? + if ( empty( $levels ) && ! empty( $level ) ) { $levels = $level; + } - // convert array to string for levels when using the block editor. + // Convert the levels attribute to an array. if ( is_array( $levels ) ) { $levels = implode( ',', $levels ); } - if($show_avatar === "0" || $show_avatar === "false" || $show_avatar === "no" || $show_avatar === false) - $show_avatar = false; - else - $show_avatar = true; - - if($show_email === "0" || $show_email === "false" || $show_email === "no" || $show_email === false ) - $show_email = false; - else - $show_email = true; - - if($show_level === "0" || $show_level === "false" || $show_level === "no" || $show_level === false) - $show_level = false; - else - $show_level = true; - - if($show_search === "0" || $show_search === "false" || $show_search === "no" || $show_search === false ) - $show_search = false; - else - $show_search = true; - - if($show_startdate === "0" || $show_startdate === "false" || $show_startdate === "no" || $show_startdate === false ) - $show_startdate = false; - else - $show_startdate = true; - - if(isset($_REQUEST['ps'])) - $s = $_REQUEST['ps']; - else - $s = ""; - // Set the default order value to be either ASC or DESC. if ( $order !== 'DESC' ) { $order = 'ASC'; } - if(isset($_REQUEST['pn'])) - $pn = intval($_REQUEST['pn']); - else - $pn = 1; - - if(isset($_REQUEST['limit'])) - $limit = intval($_REQUEST['limit']); - elseif(empty($limit)) - $limit = 15; + // Set some values from the request or defaults. + $s = isset( $_REQUEST['ps'] ) ? sanitize_text_field( $_REQUEST['ps'] ) : ''; // Search string. + $pn = isset( $_REQUEST['pn'] ) ? intval( $_REQUEST['pn'] ) : 1; // Page number. + $limit = isset($_REQUEST['limit']) ? intval($_REQUEST['limit']) : (empty($limit) ? 15 : $limit); $end = $pn * $limit; $start = $end - $limit; @@ -138,9 +99,9 @@ function pmpromd_shortcode($atts, $content=null, $code="") */ $sql_search_where = apply_filters( 'pmpro_member_directory_sql_search_where', $sql_search_where, $s ); - $sql_parts['JOIN'] .= "LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id "; - $sql_parts['WHERE'] .= $sql_search_where; -} + $sql_parts['JOIN'] .= "LEFT JOIN $wpdb->usermeta um ON u.ID = um.user_id "; + $sql_parts['WHERE'] .= $sql_search_where; + } // If levels are passed in. if ( $levels ) { @@ -158,8 +119,8 @@ function pmpromd_shortcode($atts, $content=null, $code="") $theusers = $wpdb->get_results($sqlQuery); $totalrows = $wpdb->get_var("SELECT FOUND_ROWS() as found_rows"); - //update end to match totalrows if total rows is small - if($totalrows < $end) + // Update end to match totalrows if total rows is small. + if ( $totalrows < $end ) $end = $totalrows; $theusers = apply_filters( 'pmpromd_user_directory_results', $theusers ); @@ -167,20 +128,11 @@ function pmpromd_shortcode($atts, $content=null, $code="") ob_start(); ?>
- - - +

@@ -189,19 +141,19 @@ function pmpromd_shortcode($atts, $content=null, $code="") - - 0) { ?> - - () - -

+ 0 ) { ?> +

+ +

+ - if ( ! empty( $fields ) ) { - // Check to see if the Block Editor is used or the shortcode. - if ( strpos( $fields, "\n" ) !== FALSE ) { - $fields = rtrim( $fields, "\n" ); // clear up a stray \n - $fields_array = explode("\n", $fields); // For new block editor. + options ) ) { - $rh_fields[$field->name] = $field->options; + // We need to support the legacy attributes for backwards compatibility. + $elements = ''; + if ( $layout == 'table' ) { + if ( ! empty( $show_avatar ) ) { + $elements .= __( 'Avatar', 'pmpro-member-directory' ) . ',avatar|' . $avatar_size . ';'; + } + $elements .= __( 'Member', 'pmpro-member-directory' ) . ',display_name;'; + } else { + if ( ! empty( $show_avatar ) ) { + $elements .= 'avatar|' . $avatar_size . ';'; } + $elements .= 'display_name;'; + } + if ( ! empty( $show_email ) ) { + $elements .= __( 'Email Address', 'pmpro-member-directory' ) . ', user_email;'; } + // These are the fields that are not part of the user object and need special handling. + if ( ! empty( $show_level ) ) { + $elements .= __( 'Level', 'pmpro-member-directory' ) . ',membership_name;'; + } + if ( ! empty( $show_startdate ) ) { + $elements .= __( 'Start Date', 'pmpro-member-directory' ) . ',membership_startdate;'; + } + if ( ! empty( $fields ) ) { + $elements .= $fields; + } + $elements_array = pmpromd_prepare_elements_array( $elements ); } - } + + /** + * Filter the elements array for the member directory. + * + * @since TBD + * @param array $elements_array The array of elements to display on the member directory. + * @param object $pu The user object. + * @return array $elements_array The array of elements to display on the member directory. + */ + $elements_array = apply_filters( 'pmpro_member_directory_elements', $elements_array ); ?> - $avatar_size, + 'elements' => $elements, 'fields' => $fields, 'layout' => $layout, 'level' => $level, @@ -292,289 +249,105 @@ function pmpromd_shortcode($atts, $content=null, $code="") 'show_level' => $show_level, 'show_search' => $show_search, 'show_startdate' => $show_startdate, - 'avatar_align' => $avatar_align, - 'fields_array' => $fields_array + 'avatar_align' => $avatar_align, + 'elements_array' => $elements_array, + 'fields_array' => $elements_array, // Backwards compatibility. We can remove this in a future version. ) ); do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); ?> - -
+ +
- - - - - - - - - - - - - - - - - - - ID); - $auser->membership_level = pmpro_getMembershipLevelForUser($auser->ID); - $user_fields_array = pmpromd_filter_profile_fields_for_levels( $fields_array, $auser ); - $count++; - - // Show the header for the user. - if ( $layout == 'table' ) { - ?> - "> - ID ); + ?> + + + + + + + + + +
- - - - - - - - - - - - - + + +
> + + + +
+
+
+ ID ); ?>
- - - - ID, $avatar_size, NULL, $auser->user_nicename ); ?> - - ID, $avatar_size, NULL, $auser->user_nicename ); ?> - - - -
- - ID, $avatar_size, NULL, $auser->display_name); ?> - - ID, $avatar_size, NULL, $auser->display_name); ?> - -
- -

- - - - - -

- - < class="pmpro_member_directory_email"> - - user_email, 'user_email' ); - ?> - > - - < class="pmpro_member_directory_level"> - - - ID ); - $membership_levels = array(); - if ( ! isset( $levels ) ) { - // Show all the user's levels. - foreach ( $alluserlevels as $curlevel ) { - $membership_levels[] = $curlevel->name; - } - } else { - $levels_array = explode(',', $levels); - // Show only the levels included in the directory. - foreach ( $alluserlevels as $curlevel ) { - if ( in_array( $curlevel->id, $levels_array) ) { - $membership_levels[] = $curlevel->name; + // Loop through the elements and output the content. + foreach ( $elements_array as $element ) { + $value = pmpromd_get_display_value( $element[1], $auser, 'directory' ); + if ( ! empty( $value ) ) { + ?> +
+ +
+ +
+ +
+ +
+
+ membership_levels = implode( ', ', $membership_levels ); - echo ! empty( $auser->membership_levels ) ? $auser->membership_levels : ''; - ?> - > - - < class="pmpro_member_directory_date"> - - - startdate < $min_startdate ) { - $min_startdate = $level->startdate; +
+ +
+ +
+ - > - {$field[1]}; - if ( ! empty( $meta_field ) ) { - ?> -

- - - - $value) { - $meta_field[$key] = $rh_fields[$field[1]][$value]; - } - } - ?> - - - - - - - - {$field[1]}, $field[1] ); - } - ?> -

- - < class="pmpro_member_directory_link"> - - > - - - -
- - -
-
-
@@ -625,12 +398,12 @@ function pmpromd_shortcode($atts, $content=null, $code="") ); if( $i == $pn ){ $active_class = 'class="pmpro_page_active"'; } else { $active_class = ''; } - + echo '' . $i . ''; } $counter++; - } - } + } + } ?> @@ -655,4 +428,4 @@ function pmpromd_shortcode($atts, $content=null, $code="") ob_end_clean(); return $temp_content; } -add_shortcode("pmpro_member_directory", "pmpromd_shortcode"); +add_shortcode( 'pmpro_member_directory', 'pmpromd_shortcode' ); From 654db0e2bbdd2961186b4e16cea2abc28d1bd739 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 17 Nov 2024 16:53:44 -0500 Subject: [PATCH 18/24] Removing location parameter lets just filter some things for display in the templates --- includes/functions.php | 5 +-- templates/directory.php | 77 ++++++++++++++++++++++++----------------- templates/profile.php | 6 +++- 3 files changed, 52 insertions(+), 36 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index 5e99f6e..bc7d61c 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -409,7 +409,7 @@ function pmpromd_prepare_elements_array( $elements ) { /** * Get the value of a specific element from a string of HTML. */ -function pmpromd_get_display_value( $element, $pu, $location = 'profile' ) { +function pmpromd_get_display_value( $element, $pu ) { // Is this a user field? if ( class_exists( 'PMPro_Field_Group' ) ) { $user_field = PMPro_Field_Group::get_field( $element[1] ); @@ -464,9 +464,6 @@ function pmpromd_get_display_value( $element, $pu, $location = 'profile' ) { switch ( $element ) { case 'display_name': $value = pmpro_member_directory_get_member_display_name( $pu ); - if ( $location == 'profile' ) { - $value = '

' . $value . '

'; - } break; case 'avatar': $value = get_avatar( $pu->ID, $avatar_size, NULL, $pu->display_name ); diff --git a/templates/directory.php b/templates/directory.php index 4ddd869..dd6c612 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -225,36 +225,43 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { * @return array $elements_array The array of elements to display on the member directory. */ $elements_array = apply_filters( 'pmpro_member_directory_elements', $elements_array ); - ?> - $avatar_size, - 'elements' => $elements, - 'fields' => $fields, - 'layout' => $layout, - 'level' => $level, - 'levels' => $levels, - 'limit' => $limit, - 'link' => $link, - 'order_by' => $order_by, - 'order' => $order, - 'show_avatar' => $show_avatar, - 'show_email' => $show_email, - 'show_level' => $show_level, - 'show_search' => $show_search, - 'show_startdate' => $show_startdate, - 'avatar_align' => $avatar_align, - 'elements_array' => $elements_array, - 'fields_array' => $elements_array, // Backwards compatibility. We can remove this in a future version. - ) ); - - do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); ?> + // Set up an array of items that will be linked to the user's profile. + $linked_elements = array( 'display_name' ); + foreach ( $elements_array as $element ) { + if ( strpos( $element[1], 'avatar|' ) !== false ) { + $linked_elements[] = $element[1]; + } + } + + /** + * Filter to override the attributes passed into the shortcode. + * + * @param array Contains all of the shortcode attributes used in the directory shortcode + */ + $shortcode_atts = apply_filters( 'pmpro_member_directory_before_atts', array( + 'avatar_size' => $avatar_size, + 'elements' => $elements, + 'fields' => $fields, + 'layout' => $layout, + 'level' => $level, + 'levels' => $levels, + 'limit' => $limit, + 'link' => $link, + 'order_by' => $order_by, + 'order' => $order, + 'show_avatar' => $show_avatar, + 'show_email' => $show_email, + 'show_level' => $show_level, + 'show_search' => $show_search, + 'show_startdate' => $show_startdate, + 'avatar_align' => $avatar_align, + 'elements_array' => $elements_array, + 'fields_array' => $elements_array, // Backwards compatibility. We can remove this in a future version. + ) ); + + do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); + ?>
ID ); ?>" class=""> ' . $value . ''; + } ?> > @@ -317,8 +328,12 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { ' . $value . ''; + } ?>
diff --git a/templates/profile.php b/templates/profile.php index 29dd8d6..5c60153 100644 --- a/templates/profile.php +++ b/templates/profile.php @@ -123,8 +123,12 @@ function pmpromd_profile_shortcode( $atts, $content=null, $code="" ) {
' . $value . ''; + } ?>
From 8b8f843a57df6123ad6b79f3571fc9e1d01a390b Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Mon, 18 Nov 2024 06:37:34 -0500 Subject: [PATCH 19/24] Start of styling individual profile; support for shipping or billing address --- css/pmpro-member-directory.css | 22 ++++++++++++++++++++-- includes/functions.php | 24 ++++++++++++++++++++++++ templates/profile.php | 4 ++-- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/css/pmpro-member-directory.css b/css/pmpro-member-directory.css index 58c314c..4ca3c45 100644 --- a/css/pmpro-member-directory.css +++ b/css/pmpro-member-directory.css @@ -86,12 +86,30 @@ div.pmpro_member_profile strong {display: block; } .pmpro_member_profile { .pmpro_card_content { - display: flex; - flex-direction: column; gap: var(--pmpro--base--spacing--medium); margin-top: var(--pmpro--base--spacing--medium); + + .pmpro_member_profile_field { + box-sizing: border-box; + flex: 1 1 calc(50% - var(--pmpro--base--spacing--medium)); + } + + .pmpro_member_profile_field_label { + font-weight: 700; + } + + /* Full width profile items */ + .pmpro_member_profile_field-display_name, + .pmpro_member_profile_field-description { + flex: 1 1 100%; + } + + .pmpro_member_profile_field-display_name h2 { + margin: 0; + } } } + .pmpro_member_profile .pmpromd_filename { display: block; } diff --git a/includes/functions.php b/includes/functions.php index bc7d61c..b3287d4 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -477,6 +477,30 @@ function pmpromd_get_display_value( $element, $pu ) { case 'membership_enddate': $value = $pu->membership_level->enddate; break; + case 'pmpro_billing_address': + $value = pmpro_formatAddress( + trim( $pu->pmpro_bfirstname . ' ' . $pu->pmpro_blastname ), + $pu->pmpro_baddress1, + $pu->pmpro_baddress2, + $pu->pmpro_bcity, + $pu->pmpro_bstate, + $pu->pmpro_bzipcode, + $pu->pmpro_bcountry, + $pu->pmpro_bphone + ); + break; + case 'pmpro_shipping_address': + $value = pmpro_formatAddress( + trim( $pu->pmpro_sfirstname . ' ' . $pu->pmpro_slastname ), + $pu->pmpro_saddress1, + $pu->pmpro_saddress2, + $pu->pmpro_scity, + $pu->pmpro_sstate, + $pu->pmpro_szipcode, + $pu->pmpro_scountry, + $pu->pmpro_sphone + ); + break; } // If we still do not have a value, try usermeta. diff --git a/templates/profile.php b/templates/profile.php index 5c60153..5dc44ee 100644 --- a/templates/profile.php +++ b/templates/profile.php @@ -68,7 +68,7 @@ function pmpromd_profile_shortcode( $atts, $content=null, $code="" ) { $elements .= __( 'Start Date', 'pmpro-member-directory' ) . ',membership_startdate;'; } if ( ! empty( $show_billing ) ) { - $elements .= __( 'Address', 'pmpro-member-directory' ) . ',pmpro_baddress1|pmpro_baddress2|pmpro_bcity|pmpro_bstate|pmpro_bzipcode|pmpro_bcountry;'; + $elements .= __( 'Address', 'pmpro-member-directory' ) . ',pmpro_billing_address;'; } if ( ! empty( $show_phone ) ) { $elements .= __( 'Phone Number', 'pmpro-member-directory' ) . ',pmpro_bphone;'; @@ -130,7 +130,7 @@ function pmpromd_profile_shortcode( $atts, $content=null, $code="" ) { $value = '

' . $value . '

'; } ?> -
+
From 47ebb8f42dec7a31384591e26263fca7905029e3 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Mon, 18 Nov 2024 06:38:37 -0500 Subject: [PATCH 20/24] Flex wrap --- css/pmpro-member-directory.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/css/pmpro-member-directory.css b/css/pmpro-member-directory.css index 4ca3c45..40a0e96 100644 --- a/css/pmpro-member-directory.css +++ b/css/pmpro-member-directory.css @@ -86,6 +86,8 @@ div.pmpro_member_profile strong {display: block; } .pmpro_member_profile { .pmpro_card_content { + display: flex; + flex-wrap: wrap; gap: var(--pmpro--base--spacing--medium); margin-top: var(--pmpro--base--spacing--medium); From 2c87b46d6814aba91e9b72d489cd9941c72ffd07 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Tue, 19 Nov 2024 16:39:23 -0500 Subject: [PATCH 21/24] Styling a bit on directory, page numbers --- css/pmpro-member-directory.css | 83 +++++++++++++++++++++++++--------- templates/directory.php | 61 +++++++++++++------------ 2 files changed, 94 insertions(+), 50 deletions(-) diff --git a/css/pmpro-member-directory.css b/css/pmpro-member-directory.css index 40a0e96..33f63bf 100644 --- a/css/pmpro-member-directory.css +++ b/css/pmpro-member-directory.css @@ -37,25 +37,23 @@ div.pmpro_member_profile strong {display: block; } .pmpro_card { margin: 0; - .pmpro_card_title a { - text-decoration: none; - } - .pmpro_card_title a:hover { - text-decoration: underline; - } - - .pmpro_card_title.pmpro_heading-avatar-right { - flex-direction: row-reverse; - justify-content: space-between; - } - .pmpro_card_title.pmpro_heading-avatar-top { - align-items: flex-start; - flex-direction: column; - } .pmpro_card_content { display: flex; flex-direction: column; gap: var(--pmpro--base--spacing--small); + margin-top: var(--pmpro--base--spacing--medium); + + .pmpro_member_profile_field_label { + font-weight: 700; + } + + .pmpro_member_profile_field-display_name { + + h2 { + font-weight: 700; + margin: 0; + } + } } .pmpro_card_actions { @@ -74,12 +72,18 @@ div.pmpro_member_profile strong {display: block; } } /* single directory item in list */ -.pmpro_member_directory .pmpro_member_directory-item, -.pmpro_member_directory .pmpro_member_directory_row { - word-break: break-word; -} -.pmpro_member_directory_link { - word-break: normal; +.pmpro_member_directory { + .pmpro_member_directory-item { + word-break: break-word; + } + + .pmpro_member_directory_row { + word-break: break-word; + } + + .pmpro_member_directory_link { + word-break: normal; + } } /* single profile item */ @@ -127,6 +131,43 @@ div.pmpro_member_profile strong {display: block; } /** * Pagination/page numbers */ +.pmpro_member_directory_pagination { + display: flex; + justify-content: center; + align-items: center; + gap: var(--pmpro--base--spacing--small); + margin: var(--pmpro--base--spacing--medium) 0; + + a { + background-color: var(--pmpro--color--base); + border: 1px solid var(--pmpro--color--border--variation); + border-radius: var(--pmpro--base--border-radius); + color: var(--pmpro--color--contrast); + padding: 2px var(--pmpro--base--spacing--small); + text-decoration: none; + transition: background-color 0.2s, border-color 0.2s, color 0.2s; + + &:hover { + background-color: var(--pmpro--color--accent--variation); + border-color: var(--pmpro--color--accent--variation); + color: var(--pmpro--color--base); + } + + &.pmpro_member_directory_pagination-current { + background-color: var(--pmpro--color--accent); + color: var(--pmpro--color--base); + cursor: default; + font-weight: 700; + } + + &.pmpro_member_directory_pagination-previous { + margin-right: 0; + } + } + +} + +/* This is legacy pagination styling we can leave in here until we remove templating. */ .pmpro_page_numbers a { padding: 6px; } diff --git a/templates/directory.php b/templates/directory.php index dd6c612..db194b0 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -295,7 +295,7 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { $value = '' . $value . ''; } ?> - > + > ' . $value . ''; } + if ( 'display_name' === $element[1] ) { + $value = '

' . $value . '

'; + } ?> -
+
@@ -377,7 +380,7 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { do_action( 'pmpro_member_directory_after', $sqlQuery, $shortcode_atts ); ?> -
+
1 ) { @@ -388,39 +391,39 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { ); $query_args = apply_filters( 'pmpromd_pagination_url', $query_args, 'prev' ); ?> - « + - - ID ) ) ) . '" title="' . esc_attr__( 'Previous', 'pmpromd' ) . '">...'; - } - - if ( round( $number_of_pages, 0 ) !== 1 && $pn !== 1 ) { - //If there's only one page, no need to show the page numbers - for( $i = $pn; $i <= $number_of_pages; $i++ ){ - if( $counter <= 6 ){ - $query_args = array( - 'ps' => $s, - 'pn' => $i, - 'limit' => $limit, - ); - - if( $i == $pn ){ $active_class = 'class="pmpro_page_active"'; } else { $active_class = ''; } + $counter = 0; + if ( empty( $pn ) || $pn != 1 ) { + echo '...'; + } - echo '' . $i . ''; - } - $counter++; + if ( round( $number_of_pages, 0 ) !== 1 && $pn !== 1 ) { + //If there's only one page, no need to show the page numbers + for( $i = $pn; $i <= $number_of_pages; $i++ ){ + if( $counter <= 6 ){ + $query_args = array( + 'ps' => $s, + 'pn' => $i, + 'limit' => $limit, + ); + + $classes = array(); + $classes[] = 'pmpro_member_directory_pagination-page'; + if ( $i == $pn ) { + $classes[] = 'pmpro_member_directory_pagination-current'; } + $classes = implode( ' ', $classes ); + echo '' . $i . ''; } - ?> - + $counter++; + } + } + ?> - » + From 9ebc0ac7c6f9b447217e182b6dfc0a8f1582bfe0 Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Tue, 26 Nov 2024 14:08:46 -0500 Subject: [PATCH 22/24] Styling for videos, audios --- css/pmpro-member-directory.css | 51 ++++++++++++++++++++++++++++++++++ includes/functions.php | 25 ++++++++++++++--- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/css/pmpro-member-directory.css b/css/pmpro-member-directory.css index 33f63bf..6601332 100644 --- a/css/pmpro-member-directory.css +++ b/css/pmpro-member-directory.css @@ -98,6 +98,40 @@ div.pmpro_member_profile strong {display: block; } .pmpro_member_profile_field { box-sizing: border-box; flex: 1 1 calc(50% - var(--pmpro--base--spacing--medium)); + + &:has(iframe) { + flex-basis: 100%; + height: 0; + overflow: hidden; + padding-bottom: 56.25%; + position: relative; + width: 100%; + + iframe { + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; + } + } + + &:has(audio) { + flex-basis: 100%; + + audio { + width: 100%; + } + } + + &:has(video) { + flex-basis: 100%; + + video { + width: 100%; + } + } + } .pmpro_member_profile_field_label { @@ -128,6 +162,23 @@ div.pmpro_member_profile strong {display: block; } } } +/** + * Special user field formatting. + */ +.pmpro_member_profile_field_data:has([class*="pmpro_form_field-file-subtype_"]) { + + a { + align-items: center; + display: flex; + gap: var(--pmpro--base--spacing--small); + + img { + max-height: 40px; + width: auto; + } + } +} + /** * Pagination/page numbers */ diff --git a/includes/functions.php b/includes/functions.php index b3287d4..2975be8 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -412,18 +412,19 @@ function pmpromd_prepare_elements_array( $elements ) { function pmpromd_get_display_value( $element, $pu ) { // Is this a user field? if ( class_exists( 'PMPro_Field_Group' ) ) { - $user_field = PMPro_Field_Group::get_field( $element[1] ); + $user_field = PMPro_Field_Group::get_field( $element ); } else { - $user_field = pmpro_get_user_field( $element[1] ); + $user_field = pmpro_get_user_field( $element ); } // Yes, this is a user field. Check that the user has the required level for this field. if ( ! empty( $user_field ) ) { + if ( ! empty( $user_field->levels ) && ! pmpro_hasMembershipLevel( $user_field->levels, $pu->ID ) ) { // The user does not have the required level for this field. return ''; } - $value = $pu->{$element[1]}; + $value = $pu->{$element}; return $user_field->displayValue( $value, false ); } else { // Let's try to get the value from other places and format it for return. @@ -503,9 +504,25 @@ function pmpromd_get_display_value( $element, $pu ) { break; } - // If we still do not have a value, try usermeta. + // If we still do not have a value, try usermeta and format using User Fields display method. if ( empty( $value ) ) { $value = $pu->$element; + + // Try to guess the field type, default to text. + $field_type = 'text'; + + // Special handling for arrays. + if ( is_array( $value ) ) { + if ( isset( $value['filename'] ) ) { + $field_type = 'file'; + } else { + $field_type = 'multiselect'; + } + } + + // Create a new PMPro_Field object. + $user_field = new PMPro_Field( $element, $field_type ); + $value = $user_field->displayValue( $value, false ); } // Format the date fields. From 3d92688d9104e57fad8281e407729274932dbfdd Mon Sep 17 00:00:00 2001 From: Kim Coleman Date: Sun, 1 Dec 2024 08:36:10 -0500 Subject: [PATCH 23/24] Logic to handle only showing info about selected levels when showing level name, start date, or enddate --- includes/functions.php | 29 ++++++++++++++++++++--------- templates/directory.php | 7 +++++-- templates/profile.php | 21 ++++++++++++++++----- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index 2975be8..3970956 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -409,7 +409,7 @@ function pmpromd_prepare_elements_array( $elements ) { /** * Get the value of a specific element from a string of HTML. */ -function pmpromd_get_display_value( $element, $pu ) { +function pmpromd_get_display_value( $element, $pu, $displayed_levels = null ) { // Is this a user field? if ( class_exists( 'PMPro_Field_Group' ) ) { $user_field = PMPro_Field_Group::get_field( $element ); @@ -445,13 +445,24 @@ function pmpromd_get_display_value( $element, $pu ) { // Check if the $element is a PMPro level field. if ( in_array( $element, $pmpro_level_fields ) ) { - $pu->membership_level = pmpro_getMembershipLevelForUser( $pu->ID ); - $allmylevels = pmpro_getMembershipLevelsForUser( $pu->ID ); - $membership_levels = array(); - foreach ( $allmylevels as $curlevel ) { - $membership_levels[] = $curlevel->name; + // Get all levels for the user. + $all_levels_to_display = pmpro_getMembershipLevelsForUser( $pu->ID ); + + // Filter levels if $displayed_levels is set and not 'all'. + if ( ! empty( $displayed_levels ) && $displayed_levels !== 'all' ) { + $displayed_levels = explode( ',', $displayed_levels ); + $all_levels_to_display = array_filter( $all_levels_to_display, fn( $level ) => in_array( $level->id, $displayed_levels ) ); } - $pu->membership_levels = implode(', ', $membership_levels); + + // Get the names of the levels to display. + $pu->membership_levels = implode( ', ', array_column( $all_levels_to_display, 'name' ) ); + + // Calculate the oldest start date and the soonest end date, if levels are available. + $start_dates = array_column( $all_levels_to_display, 'startdate' ); + $end_dates = array_column( $all_levels_to_display, 'enddate' ); + + $startdate = ! empty( $start_dates ) ? min( $start_dates ) : null; + $enddate = ! empty( $end_dates ) ? min( $end_dates ) : null; } // Get the avatar_size for the avatar element. @@ -473,10 +484,10 @@ function pmpromd_get_display_value( $element, $pu ) { $value = $pu->membership_levels; break; case 'membership_startdate': - $value = $pu->membership_level->startdate; + $value = $startdate; break; case 'membership_enddate': - $value = $pu->membership_level->enddate; + $value = $enddate; break; case 'pmpro_billing_address': $value = pmpro_formatAddress( diff --git a/templates/directory.php b/templates/directory.php index db194b0..99cae83 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -260,6 +260,9 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { 'fields_array' => $elements_array, // Backwards compatibility. We can remove this in a future version. ) ); + // Set the displayed_levels variable to use for displaying values. + $displayed_levels = empty( $levels ) ? 'all' : $levels; + do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); ?> @@ -289,7 +292,7 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { ' . $value . ''; @@ -328,7 +331,7 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { '128', 'elements' => NULL, 'fields' => NULL, + 'level' => NULL, + 'levels' => NULL, 'show_avatar' => true, 'show_bio' => true, 'show_billing' => true, @@ -28,6 +30,16 @@ function pmpromd_profile_shortcode( $atts, $content=null, $code="" ) { // Get the user for this profile. $pu = pmpromd_get_user( $user_id ); + // Did they use level instead of levels? + if ( empty( $levels ) && ! empty( $level ) ) { + $levels = $level; + } + + // Convert the levels attribute to an array. + if ( is_array( $levels ) ) { + $levels = implode( ',', $levels ); + } + // Validate boolean variables. $show_avatar = filter_var( $show_avatar, FILTER_VALIDATE_BOOLEAN ); $show_billing = filter_var( $show_billing, FILTER_VALIDATE_BOOLEAN ); @@ -89,6 +101,9 @@ function pmpromd_profile_shortcode( $atts, $content=null, $code="" ) { */ $elements_array = apply_filters( 'pmpro_member_profile_elements', $elements_array, $pu ); + // Set the displayed_levels variable to use for displaying values. + $displayed_levels = empty( $levels ) ? 'all' : $levels; + if(isset($_REQUEST['limit'])) $limit = intval($_REQUEST['limit']); elseif(empty($limit)) @@ -103,10 +118,6 @@ function pmpromd_profile_shortcode( $atts, $content=null, $code="" ) { } ?> - -
"> Date: Wed, 4 Dec 2024 09:14:42 -0500 Subject: [PATCH 24/24] Wrapping the content displayed before and after hte directory for styling; fixing case where profile_url is not set --- templates/directory.php | 374 +++++++++++++++++++++------------------- 1 file changed, 193 insertions(+), 181 deletions(-) diff --git a/templates/directory.php b/templates/directory.php index 99cae83..c962c5f 100644 --- a/templates/directory.php +++ b/templates/directory.php @@ -134,137 +134,146 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { } ?> -

- - - %s.','pmpro-member-directory'), stripslashes( ucwords(esc_html($s)))); ?> - - +
+

+ + + %s.','pmpro-member-directory'), stripslashes( ucwords(esc_html($s)))); ?> + + + +

+ 0 ) { ?> +

+ +

-

- 0 ) { ?> -

- -

- - -
+
+ %s.', 'pmpro-member-directory' ), stripslashes( ucwords( esc_html( $s ) ) ) ) ); + + // If there is a directory URL, display a link to view all members. + if ( ! empty( $directory_url ) ) { + ?> + + +
%s.', 'pmpro-member-directory' ), stripslashes( ucwords( esc_html( $s ) ) ) ) ); + $temp_content = ob_get_contents(); + ob_end_clean(); + return $temp_content; + } + ?> - // If there is a directory URL, display a link to view all members. - if ( ! empty( $directory_url ) ) { - ?> - - -
- - - $avatar_size, - 'elements' => $elements, - 'fields' => $fields, - 'layout' => $layout, - 'level' => $level, - 'levels' => $levels, - 'limit' => $limit, - 'link' => $link, - 'order_by' => $order_by, - 'order' => $order, - 'show_avatar' => $show_avatar, - 'show_email' => $show_email, - 'show_level' => $show_level, - 'show_search' => $show_search, - 'show_startdate' => $show_startdate, - 'avatar_align' => $avatar_align, - 'elements_array' => $elements_array, - 'fields_array' => $elements_array, // Backwards compatibility. We can remove this in a future version. - ) ); - - // Set the displayed_levels variable to use for displaying values. - $displayed_levels = empty( $levels ) ? 'all' : $levels; - - do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); - ?> + /** + * Filter to override the attributes passed into the shortcode. + * + * @param array Contains all of the shortcode attributes used in the directory shortcode + */ + $shortcode_atts = apply_filters( 'pmpro_member_directory_before_atts', array( + 'avatar_size' => $avatar_size, + 'elements' => $elements, + 'fields' => $fields, + 'layout' => $layout, + 'level' => $level, + 'levels' => $levels, + 'limit' => $limit, + 'link' => $link, + 'order_by' => $order_by, + 'order' => $order, + 'show_avatar' => $show_avatar, + 'show_email' => $show_email, + 'show_level' => $show_level, + 'show_search' => $show_search, + 'show_startdate' => $show_startdate, + 'avatar_align' => $avatar_align, + 'elements_array' => $elements_array, + 'fields_array' => $elements_array, // Backwards compatibility. We can remove this in a future version. + ) ); + + // Set the displayed_levels variable to use for displaying values. + $displayed_levels = empty( $levels ) ? 'all' : $levels; + + /** + * Action to add content before the member directory. + * + * @since 0.8 + * @param string $sqlQuery The SQL query used to get the members. + * @param array $shortcode_atts The attributes passed into the shortcode. + */ + do_action( 'pmpro_member_directory_before', $sqlQuery, $shortcode_atts ); + ?> +
' . $value . ''; } ?> @@ -334,7 +343,7 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { $value = pmpromd_get_display_value( $element[1], $auser, $displayed_levels ); if ( ! empty( $value ) ) { // Wrap the value in a link if the element is in the linked elements array. - if ( ! empty( $link ) && in_array( $element[1], $linked_elements ) ) { + if ( ! empty( $link ) && ! empty( $profile_url ) &&in_array( $element[1], $linked_elements ) ) { $value = '' . $value . ''; } if ( 'display_name' === $element[1] ) { @@ -372,77 +381,80 @@ function pmpromd_shortcode( $atts, $content=null, $code="" ) { } ?>
- -
+
1 ) { - $query_args = array( - 'ps' => $s, - 'pn' => $pn-1, - 'limit' => $limit, - ); - $query_args = apply_filters( 'pmpromd_pagination_url', $query_args, 'prev' ); - ?> - + /** + * Action to add content after the member directory. + * + * @since 0.8 + * @param string $sqlQuery The SQL query used to get the members. + * @param array $shortcode_atts The attributes passed into the shortcode. + */ + do_action( 'pmpro_member_directory_after', $sqlQuery, $shortcode_atts ); + ?> + +
1 ) { + $query_args = array( + 'ps' => $s, + 'pn' => $pn-1, + 'limit' => $limit, + ); + $query_args = apply_filters( 'pmpromd_pagination_url', $query_args, 'prev' ); + ?> + + ID ) ) ) . '" title="' . esc_attr__( 'Previous', 'pmpromd' ) . '">...'; - } + $number_of_pages = $totalrows / $limit; + //Page Numbers + $counter = 0; + if ( empty( $pn ) || $pn != 1 ) { + echo '...'; + } - if ( round( $number_of_pages, 0 ) !== 1 && $pn !== 1 ) { - //If there's only one page, no need to show the page numbers - for( $i = $pn; $i <= $number_of_pages; $i++ ){ - if( $counter <= 6 ){ - $query_args = array( - 'ps' => $s, - 'pn' => $i, - 'limit' => $limit, - ); - - $classes = array(); - $classes[] = 'pmpro_member_directory_pagination-page'; - if ( $i == $pn ) { - $classes[] = 'pmpro_member_directory_pagination-current'; + if ( round( $number_of_pages, 0 ) !== 1 && $pn !== 1 ) { + //If there's only one page, no need to show the page numbers + for( $i = $pn; $i <= $number_of_pages; $i++ ){ + if( $counter <= 6 ){ + $query_args = array( + 'ps' => $s, + 'pn' => $i, + 'limit' => $limit, + ); + + $classes = array(); + $classes[] = 'pmpro_member_directory_pagination-page'; + if ( $i == $pn ) { + $classes[] = 'pmpro_member_directory_pagination-current'; + } + $classes = implode( ' ', $classes ); + echo '' . $i . ''; } - $classes = implode( ' ', $classes ); - echo '' . $i . ''; + $counter++; } - $counter++; } - } - ?> - - $end ) { - $query_args = array( - 'ps' => $s, - 'pn' => $pn+1, - 'limit' => $limit, - ); - $query_args = apply_filters( 'pmpromd_pagination_url', $query_args, 'next' ); ?> - + -
+ //next + if ( $totalrows > $end ) { + $query_args = array( + 'ps' => $s, + 'pn' => $pn+1, + 'limit' => $limit, + ); + $query_args = apply_filters( 'pmpromd_pagination_url', $query_args, 'next' ); + ?> + + +
+