Created
September 2, 2026 18:15
-
-
Save rickalday/64ccb265b31366cd718a8670ea889f67 to your computer and use it in GitHub Desktop.
Fix donor wall shortcode
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| add_action( 'init', function () { | |
| remove_shortcode( 'give_donor_wall' ); | |
| add_shortcode( 'give_donor_wall', 'my_safe_give_donor_wall_shortcode' ); | |
| }, 100 ); | |
| function my_safe_give_donor_wall_shortcode( $atts = [] ) { | |
| $atts = shortcode_atts( | |
| [ | |
| 'donors_per_page' => 12, | |
| 'form_id' => 0, | |
| 'paged' => 1, | |
| 'ids' => '', | |
| 'cats' => '', | |
| 'tags' => '', | |
| 'columns' => '3', | |
| 'anonymous' => true, | |
| 'show_avatar' => true, | |
| 'show_name' => true, | |
| 'show_company_name' => false, | |
| 'show_form' => false, | |
| 'show_total' => true, | |
| 'show_comments' => true, | |
| 'show_tributes' => true, | |
| 'comment_length' => 140, | |
| 'only_comments' => false, | |
| 'readmore_text' => esc_html__( 'Read more', 'give' ), | |
| 'loadmore_text' => esc_html__( 'Load more', 'give' ), | |
| 'avatar_size' => 75, | |
| 'color' => '#219653', | |
| 'orderby' => 'post_date', | |
| 'order' => 'DESC', | |
| 'show_time' => true, | |
| 'only_donor_html' => false, | |
| ], | |
| $atts, | |
| 'give_donor_wall' | |
| ); | |
| // Boolean normalization | |
| foreach ( | |
| [ | |
| 'anonymous', | |
| 'show_avatar', | |
| 'show_name', | |
| 'show_company_name', | |
| 'show_form', | |
| 'show_total', | |
| 'show_comments', | |
| 'show_tributes', | |
| 'only_comments', | |
| 'show_time', | |
| 'only_donor_html' | |
| ] as $key | |
| ) { | |
| if ( is_numeric( $atts[ $key ] ) ) { | |
| $atts[ $key ] = (bool) $atts[ $key ]; | |
| } | |
| $atts[ $key ] = filter_var( $atts[ $key ], FILTER_VALIDATE_BOOLEAN ); | |
| } | |
| foreach ( [ 'donors_per_page', 'paged', 'comment_length', 'avatar_size' ] as $key ) { | |
| $atts[ $key ] = absint( $atts[ $key ] ); | |
| } | |
| global $wpdb; | |
| $donation_id_col = Give()->payment_meta->get_meta_type() . '_id'; | |
| $table = $wpdb->donationmeta; | |
| $sql = " | |
| SELECT p.ID | |
| FROM {$wpdb->posts} p | |
| INNER JOIN {$table} m1 ON ( p.ID = m1.{$donation_id_col} ) | |
| WHERE p.post_status = 'publish' | |
| AND p.post_type = 'give_payment' | |
| AND m1.meta_key = '_give_payment_total' | |
| AND m1.meta_value > 0 | |
| "; | |
| if ( ! empty( $atts['form_id'] ) ) { | |
| $form_ids = implode( "','", array_map( 'absint', explode( ',', $atts['form_id'] ) ) ); | |
| $sql .= " AND p.ID IN ( | |
| SELECT DISTINCT m2.{$donation_id_col} | |
| FROM {$table} m2 | |
| WHERE m2.meta_key = '_give_payment_form_id' | |
| AND m2.meta_value IN ('{$form_ids}') | |
| )"; | |
| } | |
| if ( ! empty( $atts['ids'] ) ) { | |
| $donor_ids = implode( "','", array_map( 'absint', explode( ',', $atts['ids'] ) ) ); | |
| $sql .= " AND p.ID IN ( | |
| SELECT DISTINCT m3.{$donation_id_col} | |
| FROM {$table} m3 | |
| WHERE m3.meta_key = '_give_payment_donor_id' | |
| AND m3.meta_value IN ('{$donor_ids}') | |
| )"; | |
| } | |
| if ( ! empty( $atts['only_comments'] ) ) { | |
| $sql .= " AND p.ID IN ( | |
| SELECT DISTINCT m4.{$donation_id_col} | |
| FROM {$table} m4 | |
| WHERE m4.meta_key = '_give_donation_comment' | |
| )"; | |
| } | |
| if ( ! $atts['anonymous'] || $atts['only_comments'] ) { | |
| $sql .= " AND p.ID NOT IN ( | |
| SELECT DISTINCT m5.{$donation_id_col} | |
| FROM {$table} m5 | |
| WHERE m5.meta_key = '_give_anonymous_donation' | |
| AND m5.meta_value = '1' | |
| )"; | |
| } | |
| $order_by = 'p.post_date'; | |
| if ( 'donation_amount' === $atts['orderby'] ) { | |
| $order_by = "( | |
| SELECT CAST(meta_value AS DECIMAL(20,2)) | |
| FROM {$table} | |
| WHERE {$donation_id_col} = p.ID | |
| AND meta_key = '_give_payment_total' | |
| LIMIT 1 | |
| )"; | |
| } | |
| $sql .= " ORDER BY {$order_by} {$atts['order']}, p.ID {$atts['order']}"; | |
| $sql .= " LIMIT " . absint( $atts['donors_per_page'] ) . " OFFSET " . absint( $atts['donors_per_page'] * ( $atts['paged'] - 1 ) ); | |
| $donation_ids = $wpdb->get_col( $sql ); | |
| if ( empty( $donation_ids ) ) { | |
| return ''; | |
| } | |
| $in = implode( ',', array_map( 'absint', $donation_ids ) ); | |
| $meta_rows = $wpdb->get_results( | |
| "SELECT m1.*, p1.post_date AS donation_date | |
| FROM {$table} AS m1 | |
| INNER JOIN {$wpdb->posts} AS p1 ON ( m1.{$donation_id_col} = p1.ID ) | |
| WHERE m1.{$donation_id_col} IN ({$in}) | |
| ORDER BY FIELD( p1.ID, {$in} )" | |
| ); | |
| $donations = []; | |
| foreach ( $meta_rows as $row ) { | |
| $donation_id = (int) $row->{$donation_id_col}; | |
| if ( ! isset( $donations[ $donation_id ] ) ) { | |
| $donations[ $donation_id ] = [ | |
| 'donation_id' => $donation_id, | |
| 'donation_date' => $row->donation_date, | |
| ]; | |
| } | |
| $value = maybe_unserialize( $row->meta_value ); | |
| $donations[ $donation_id ][ $row->meta_key ] = $value; | |
| if ( empty( $donations[ $donation_id ]['donation_date'] ) ) { | |
| $donations[ $donation_id ]['donation_date'] = $row->donation_date; | |
| } | |
| } | |
| foreach ( $donations as $donation_id => $donation_data ) { | |
| $donations[ $donation_id ]['name_initial'] = give_get_name_initial( | |
| [ | |
| 'firstname' => $donation_data['_give_donor_billing_first_name'] ?? '', | |
| 'lastname' => $donation_data['_give_donor_billing_last_name'] ?? '', | |
| ] | |
| ); | |
| $donations[ $donation_id ]['donor_comment'] = give_get_payment_meta( | |
| $donation_id, | |
| '_give_donation_comment' | |
| ); | |
| } | |
| $html = ''; | |
| foreach ( $donations as $donation ) { | |
| $donor = new Give_Donor( $donation['_give_payment_donor_id'] ?? 0 ); | |
| $primary_color = ! empty( $atts['color'] ) ? $atts['color'] : '#219653'; | |
| $avatar_size = (int) $atts['avatar_size']; | |
| $tribute_background_color = ! empty( $atts['color'] ) ? $atts['color'] . '20' : '#219653'; | |
| ob_start(); | |
| ?> | |
| <div class="give-grid__item testies"> | |
| <div class="give-donor give-card"> | |
| <div class="give-donor-container"> | |
| <?php if ( $atts['show_avatar'] ) : ?> | |
| <?php | |
| if ( ! empty( $donation['_give_anonymous_donation'] ) ) { | |
| $image_url = GIVE_PLUGIN_URL . 'build/assets/dist/images/anonymous-user.svg'; | |
| $alt = __( 'Anonymous User', 'give' ); | |
| ?> | |
| <div class='give-donor-container__image'> | |
| <img class='give-donor-container__image__anonymous' src='<?php echo esc_url( $image_url ); ?>' alt='<?php echo esc_attr( $alt ); ?>' style='<?php echo esc_attr( 'height: ' . $avatar_size . 'px;' ); ?>' /> | |
| </div> | |
| <?php | |
| } elseif ( ( $avatar = $donor->get_meta( '_give_donor_avatar_id', true ) ) ) { | |
| $image_url = wp_get_attachment_image_url( $avatar, 'thumbnail' ); | |
| $alt = __( 'Donor Avatar', 'give' ); | |
| ?> | |
| <div class='give-donor-container__image'> | |
| <img src='<?php echo esc_url( $image_url ); ?>' alt='<?php echo esc_attr( $alt ); ?>' style='<?php echo esc_attr( 'height: ' . $avatar_size . 'px;' ); ?>' /> | |
| </div> | |
| <?php | |
| } elseif ( ! empty( $donation['_give_payment_donor_email'] ) && give_validate_gravatar( $donation['_give_payment_donor_email'] ) ) { | |
| $hash = md5( strtolower( trim( $donation['_give_payment_donor_email'] ) ) ); | |
| ?> | |
| <div class='give-donor-container__image'> | |
| <img src='<?php echo esc_url( 'https://gravatar.com/avatar/' . $hash ); ?>' alt='<?php echo esc_attr( $donor->name ); ?>' style='<?php echo esc_attr( 'height: ' . $avatar_size . 'px;' ); ?>' /> | |
| </div> | |
| <?php | |
| } else { | |
| $initial = esc_html( $donation['name_initial'] ?? '' ); | |
| ?> | |
| <div class='give-donor-container__image' style='<?php echo esc_attr( 'height: ' . $avatar_size . 'px; width: ' . $avatar_size . 'px;' ); ?>'> | |
| <span class='give-donor-container__image__name_initial'><?php echo $initial; ?></span> | |
| </div> | |
| <?php | |
| } | |
| ?> | |
| <?php endif; ?> | |
| <?php | |
| $flex_direction = $atts['show_avatar'] ? 'column' : 'row'; | |
| $align_items = $atts['show_avatar'] ? 'center' : 'flex-end'; | |
| ?> | |
| <div class="give-donor-container-variation" style="<?php echo esc_attr( 'flex-direction: ' . $flex_direction . '; align-items: ' . $align_items . ';' ); ?>"> | |
| <?php if ( $atts['show_name'] ) : ?> | |
| <h3 class="give-donor-container-variation__name"> | |
| <?php | |
| $donor_name = ! empty( $donation['_give_anonymous_donation'] ) | |
| ? esc_html__( 'Anonymous', 'give' ) | |
| : trim( ( $donation['_give_donor_billing_first_name'] ?? '' ) . ' ' . ( $donation['_give_donor_billing_last_name'] ?? '' ) ); | |
| echo esc_html( $donor_name ); | |
| ?> | |
| </h3> | |
| <?php endif; ?> | |
| <?php if ( $atts['show_company_name'] && isset( $donation['_give_donation_company'] ) ) : ?> | |
| <h3 class="give-donor-container-variation__name"> | |
| <?php echo esc_html( $donation['_give_donation_company'] ); ?> | |
| </h3> | |
| <?php endif; ?> | |
| <?php if ( $atts['show_time'] ) : ?> | |
| <p class="give-donor-container-variation__timestamp"> | |
| <?php echo esc_html( give_get_formatted_date( $donation['donation_date'], give_date_format(), 'Y-m-d H:i:s', true ) ); ?> | |
| </p> | |
| <?php endif; ?> | |
| </div> | |
| <?php | |
| if ( | |
| $atts['show_comments'] | |
| && empty( $donation['_give_anonymous_donation'] ) | |
| && absint( $atts['comment_length'] ) | |
| && ! empty( $donation['donor_comment'] ) | |
| ) : | |
| $comment = esc_html( $donation['donor_comment'] ); | |
| $stripped_comment = str_replace( ' ', '', $comment ); | |
| $total_chars = strlen( $stripped_comment ); | |
| $max_chars = $atts['comment_length']; | |
| $read_more_text = $atts['readmore_text']; | |
| ?> | |
| <div class="give-donor-wrapper"> | |
| <div class="give-donor-content" style="border-color: <?php echo ! empty( $atts['color'] ) ? esc_attr( $atts['color'] ) : '#219653'; ?>"> | |
| <?php | |
| if ( $max_chars < $total_chars ) { | |
| $excerpt = ''; | |
| $offset = - ( $total_chars - $max_chars ); | |
| $last_space = strrpos( $comment, ' ', $offset ); | |
| if ( $last_space ) { | |
| $excerpt = substr( $comment, 0, $last_space ); | |
| } else { | |
| $excerpt = substr( $comment, 0, $max_chars ); | |
| } | |
| $excerpt = trim( $excerpt, '.!,:;' ); | |
| echo "<p class='give-donor-content__excerpt'>$excerpt … | |
| <span><a class='give-donor-content__read-more' style='color: " . esc_attr( $primary_color ) . "'> $read_more_text </a></span> | |
| </p>"; | |
| echo "<p class='give-donor-content__comment'> $comment </p>"; | |
| } else { | |
| echo "<p class='give-donor-content__comment'>$comment</p>"; | |
| } | |
| ?> | |
| </div> | |
| </div> | |
| <?php endif; ?> | |
| <div class="give-donor-details"> | |
| <div class="give-donor-details__wrapper"> | |
| <?php | |
| if ( isset( $donation['_give_payment_form_title'] ) ) { | |
| $full_form_name = esc_html( $donation['_give_payment_form_title'] ); | |
| $word_count = 3; | |
| preg_match( "/(\\S+\\s*){0,$word_count}/", esc_html( $donation['_give_payment_form_title'] ), $regs ); | |
| $truncated_form_name = trim( $regs[0] . "..." ); | |
| if ( $atts['show_form'] && $atts['show_total'] ) { | |
| if ( str_word_count( $donation['_give_payment_form_title'], 0 ) <= $word_count ) { | |
| echo "<span class='give-donor-details__form_title'> $full_form_name </span>"; | |
| } else { | |
| echo "<span class='give-donor-details__form_title'> $truncated_form_name </span>"; | |
| } | |
| } elseif ( $atts['show_form'] && ! $atts['show_total'] ) { | |
| echo "<span class='give-donor-details__form_title' style='text-align: center'> $full_form_name </span>"; | |
| } | |
| } | |
| if ( $atts['show_total'] ) { | |
| echo sprintf( | |
| '<span class=\'give-donor-details__amount_donated\'>%1$s</span>', | |
| esc_html__( 'Amount Donated', 'give' ) | |
| ); | |
| } | |
| ?> | |
| </div> | |
| <?php | |
| $donation_amount = give_donation_amount( (int) $donation['donation_id'], true ); | |
| if ( $atts['show_total'] ) { | |
| echo "<span class='give-donor-details__total' style='color: " . esc_attr( $primary_color ) . "'> $donation_amount </span>"; | |
| } | |
| ?> | |
| </div> | |
| </div> | |
| <?php | |
| if ( | |
| $atts['show_tributes'] | |
| && ( isset( $donation['_give_tributes_first_name'] ) || isset( $donation['_give_tributes_last_name'] ) ) | |
| ) : | |
| $tribute_message = esc_html( $donation['_give_tributes_type'] ?? '' ); | |
| $honoree_first_name = esc_html( $donation['_give_tributes_first_name'] ?? '' ); | |
| $honoree_last_name = esc_html( $donation['_give_tributes_last_name'] ?? '' ); | |
| $honoree_full_name = | |
| ! empty( $donation['_give_tributes_last_name'] ) | |
| ? trim( $honoree_first_name . ' ' . strtoupper( $honoree_last_name[0] ) . '.' ) | |
| : trim( $honoree_first_name ) . '.'; | |
| ?> | |
| <div class='give-donor-tribute' style='background-color: <?php echo esc_attr( $tribute_background_color ); ?>'> | |
| <span> | |
| <svg width='16' height='16' viewBox='0 0 16 16' xmlns='http://www.w3.org/2000/svg' class='give-donor-tribute__svg'> | |
| <path fill='<?php echo esc_attr( $primary_color ); ?>' opacity='0.4' d='M11.9667 5.13998L11.8734 5.08665L10.9467 4.55332L9.0334 3.44665C8.44673 3.10665 7.5534 3.10665 6.96673 3.44665L5.0534 4.55332L4.12673 5.09332L4.00673 5.15998C2.8134 5.95998 2.7334 6.10665 2.7334 7.39332V10.4667C2.7334 11.7533 2.8134 11.9 4.0334 12.72L6.96673 14.4133C7.26007 14.5867 7.62673 14.6667 8.00007 14.6667C8.36673 14.6667 8.74007 14.5867 9.0334 14.4133L11.9934 12.7C13.1867 11.9 13.2667 11.7533 13.2667 10.4667V7.39332C13.2667 6.10665 13.1867 5.95998 11.9667 5.13998Z' fill='#15AE56'/> | |
| <path fill='<?php echo esc_attr( $primary_color ); ?>' d='M4.12671 5.09337L5.05338 4.55337L6.88004 3.50004L6.96671 3.44671C7.55337 3.10671 8.44671 3.10671 9.03338 3.44671L9.12004 3.50004L10.9467 4.55337L11.8734 5.08671V3.66004C11.8734 2.16004 11.0467 1.33337 9.54671 1.33337H6.44671C4.94671 1.33337 4.12671 2.16004 4.12671 3.66004V5.09337Z' fill='#15AE56'/> | |
| <path fill='<?php echo esc_attr( $primary_color ); ?>' d='M9.89333 8.89327L9.47999 9.39994C9.41333 9.47327 9.36666 9.61994 9.37333 9.71994L9.41333 10.3733C9.43999 10.7733 9.15333 10.9799 8.77999 10.8333L8.17333 10.5933C8.07999 10.5599 7.91999 10.5599 7.82666 10.5933L7.21999 10.8333C6.84666 10.9799 6.55999 10.7733 6.58666 10.3733L6.62666 9.71994C6.63333 9.61994 6.58666 9.47327 6.51999 9.39994L6.10666 8.89327C5.84666 8.5866 5.95999 8.2466 6.34666 8.1466L6.97999 7.9866C7.07999 7.95994 7.19999 7.8666 7.25333 7.77994L7.60666 7.23327C7.82666 6.89327 8.17333 6.89327 8.39333 7.23327L8.74666 7.77994C8.79999 7.8666 8.91999 7.95994 9.01999 7.9866L9.65333 8.1466C10.04 8.2466 10.1533 8.5866 9.89333 8.89327Z' fill='#15AE56'/> | |
| </svg> | |
| </span> | |
| <span class='give-donor-tribute__message'> | |
| <span><?php echo $tribute_message; ?></span> | |
| <span><?php echo $honoree_full_name; ?></span> | |
| </span> | |
| </div> | |
| <?php endif; ?> | |
| </div> | |
| </div> | |
| <?php | |
| $html .= ob_get_clean(); | |
| } | |
| if ( empty( $html ) ) { | |
| return ''; | |
| } | |
| $html = sprintf( | |
| '<div class="give-wrap give-grid-ie-utility"><div class="give-grid give-grid--%1$s">%2$s</div>%3$s</div>', | |
| esc_attr( $atts['columns'] ), | |
| $html, | |
| ( $atts['only_donor_html'] ? '' : '' ) | |
| ); | |
| return $html; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment