/**
  * @param array  $atts
  * @param string $content
  * @param string $tag
  *
  * @return string
  */
 public static function shortcode($atts, $content = '', $tag = 'connections')
 {
     // Grab an instance of the Connections object.
     $instance = Connections_Directory();
     $html = '';
     if (is_customize_preview()) {
         /**
          * Hook to allow the active template to be overridden and set to the current template being customized.
          *
          * @since 8.4
          *
          * @param array $atts {
          *     @type string $template The template slug of the template being customized.
          * }
          */
         $atts = apply_filters('cn_template_customizer_template', $atts);
     }
     /** @var cnTemplate $template */
     $template = cnTemplateFactory::loadTemplate($atts);
     if ($template === FALSE) {
         return cnTemplatePart::loadTemplateError($atts);
     }
     /*
      * This filter adds the current template paths to cnLocate so when template
      * part file overrides are being searched for, it'll also search in template
      * specific paths. This filter is then removed at the end of the shortcode.
      */
     add_filter('cn_locate_file_paths', array($template, 'templatePaths'));
     self::addFilterRegistry('cn_locate_file_paths');
     do_action('cn_template_include_once-' . $template->getSlug());
     do_action('cn_template_enqueue_js-' . $template->getSlug());
     /*
      * Now that the template has been loaded, Validate the user supplied shortcode atts.
      */
     $defaults = array('id' => NULL, 'slug' => NULL, 'category' => NULL, 'category_in' => NULL, 'exclude_category' => NULL, 'category_name' => NULL, 'category_slug' => NULL, 'wp_current_category' => FALSE, 'allow_public_override' => FALSE, 'private_override' => FALSE, 'show_alphaindex' => cnSettingsAPI::get('connections', 'display_results', 'index'), 'repeat_alphaindex' => cnSettingsAPI::get('connections', 'display_results', 'index_repeat'), 'show_alphahead' => cnSettingsAPI::get('connections', 'display_results', 'show_current_character'), 'list_type' => NULL, 'order_by' => NULL, 'limit' => NULL, 'offset' => NULL, 'family_name' => NULL, 'last_name' => NULL, 'title' => NULL, 'organization' => NULL, 'department' => NULL, 'district' => NULL, 'county' => NULL, 'city' => NULL, 'state' => NULL, 'zip_code' => NULL, 'country' => NULL, 'meta_query' => '', 'content' => '', 'near_addr' => NULL, 'latitude' => NULL, 'longitude' => NULL, 'radius' => 10, 'unit' => 'mi', 'template' => NULL, 'width' => NULL, 'lock' => FALSE, 'force_home' => FALSE, 'home_id' => in_the_loop() && is_page() ? get_the_ID() : cnSettingsAPI::get('connections', 'home_page', 'page_id'));
     $defaults = apply_filters('cn_list_atts_permitted', $defaults);
     $defaults = apply_filters('cn_list_atts_permitted-' . $template->getSlug(), $defaults);
     $atts = shortcode_atts($defaults, $atts, $tag);
     $atts = apply_filters('cn_list_atts', $atts);
     $atts = apply_filters('cn_list_atts-' . $template->getSlug(), $atts);
     /*
      * Convert some of the $atts values in the array to boolean.
      */
     cnFormatting::toBoolean($atts['allow_public_override']);
     cnFormatting::toBoolean($atts['private_override']);
     cnFormatting::toBoolean($atts['show_alphaindex']);
     cnFormatting::toBoolean($atts['repeat_alphaindex']);
     cnFormatting::toBoolean($atts['show_alphahead']);
     cnFormatting::toBoolean($atts['wp_current_category']);
     cnFormatting::toBoolean($atts['lock']);
     cnFormatting::toBoolean($atts['force_home']);
     // var_dump( $atts );
     /*
      * The post editor entity encodes the post text we have to decode it
      * so a match can be made when the query is run.
      */
     $atts['family_name'] = html_entity_decode($atts['family_name']);
     $atts['last_name'] = html_entity_decode($atts['last_name']);
     $atts['title'] = html_entity_decode($atts['title']);
     $atts['organization'] = html_entity_decode($atts['organization']);
     $atts['department'] = html_entity_decode($atts['department']);
     $atts['city'] = html_entity_decode($atts['city']);
     $atts['state'] = html_entity_decode($atts['state']);
     $atts['zip_code'] = html_entity_decode($atts['zip_code']);
     $atts['country'] = html_entity_decode($atts['country']);
     $atts['category_name'] = html_entity_decode($atts['category_name']);
     if (0 < strlen($atts['meta_query'])) {
         // The meta query syntax follows the JSON standard, except, the WordPress Shortcode API does not allow
         // brackets within shortcode options, so parenthesis have to be used instead, so, lets swap them
         // that was json_decode can be ran and the resulting array used in cnRetrieve::entries().
         $atts['meta_query'] = str_replace(array('(', ')'), array('[', ']'), $atts['meta_query']);
         $metaQuery = cnFormatting::maybeJSONdecode($atts['meta_query']);
         $atts['meta_query'] = is_array($metaQuery) ? $metaQuery : array();
     }
     $atts = apply_filters('cn_list_retrieve_atts', $atts);
     $atts = apply_filters('cn_list_retrieve_atts-' . $template->getSlug(), $atts);
     $results = $instance->retrieve->entries($atts);
     // $html .= print_r( $instance->lastQuery, TRUE );
     // Apply any registered filters to the results.
     if (!empty($results)) {
         $results = apply_filters('cn_list_results', $results);
         $results = apply_filters('cn_list_results-' . $template->getSlug(), $results);
         self::addFilterRegistry('cn_list_results-' . $template->getSlug());
     }
     ob_start();
     // Prints the template's CSS file.
     // NOTE: This is primarily to support legacy templates which included a CSS
     // file which was not enqueued in the page header.
     do_action('cn_template_inline_css-' . $template->getSlug(), $atts);
     // The return to top anchor
     do_action('cn_list_return_to_target', $atts);
     $html .= ob_get_clean();
     $html .= sprintf('<div class="cn-list" id="cn-list" data-connections-version="%1$s-%2$s"%3$s>', $instance->options->getVersion(), $instance->options->getDBVersion(), empty($atts['width']) ? '' : ' style="width: ' . $atts['width'] . 'px;"');
     $html .= sprintf('<div class="cn-template cn-%1$s" id="cn-%1$s" data-template-version="%2$s">', $template->getSlug(), $template->getVersion());
     // The filter should check $content that content is not empty before processing $content.
     // And if it is empty the filter should return (bool) FALSE, so the core template parts can be executed.
     $content = apply_filters("cn_shortcode_content-{$tag}", FALSE, $content, $atts, $results, $template);
     if ($content === FALSE) {
         ob_start();
         // Render the core result list header.
         cnTemplatePart::header($atts, $results, $template);
         // Render the core result list body.
         cnTemplatePart::body($atts, $results, $template);
         // Render the core result list footer.
         cnTemplatePart::footer($atts, $results, $template);
         $html .= ob_get_clean();
     } else {
         $html .= $content;
     }
     $html .= PHP_EOL . '</div>' . (WP_DEBUG ? '<!-- END #cn-' . $template->getSlug() . ' -->' : '') . PHP_EOL;
     $html .= PHP_EOL . '</div>' . (WP_DEBUG ? '<!-- END #cn-list -->' : '') . PHP_EOL;
     // Clear any filters that have been added.
     // This allows support using the shortcode multiple times on the same page.
     cnShortcode::clearFilterRegistry();
     // @todo This should be run via a filter.
     return self::removeEOL($html);
 }
 public static function shortcode($atts, $content = '', $tag = 'cn_thumbr')
 {
     // Grab an instance of the Connections object.
     $instance = Connections_Directory();
     $log = array();
     $srcset = array();
     $permitted = array('attachment', 'featured', 'path', 'url', 'logo', 'photo');
     $defaults = array('type' => 'url', 'source' => NULL, 'negate' => FALSE, 'grayscale' => FALSE, 'brightness' => 0, 'colorize' => NULL, 'contrast' => 0, 'detect_edges' => FALSE, 'emboss' => FALSE, 'gaussian_blur' => FALSE, 'blur' => FALSE, 'sketchy' => FALSE, 'sharpen' => FALSE, 'smooth' => NULL, 'opacity' => 100, 'crop_mode' => 1, 'crop_focus' => array(0.5, 0.5), 'crop_only' => FALSE, 'canvas_color' => '#FFFFFF', 'quality' => 90, 'sizes' => '1024|640|320');
     $defaults = apply_filters('cn_thumbr_shortcode_atts', $defaults);
     $atts = shortcode_atts($defaults, $atts, $tag);
     if (!in_array($atts['type'], $permitted)) {
         return __('Valid image source type not supplied.', 'connections');
     }
     /*
      * Convert some of the $atts values in the array to boolean because the Shortcode API passes all values as strings.
      */
     cnFormatting::toBoolean($atts['negate']);
     cnFormatting::toBoolean($atts['grayscale']);
     cnFormatting::toBoolean($atts['detect_edges']);
     cnFormatting::toBoolean($atts['emboss']);
     cnFormatting::toBoolean($atts['gaussian_blur']);
     cnFormatting::toBoolean($atts['blur']);
     cnFormatting::toBoolean($atts['sketchy']);
     cnFormatting::toBoolean($atts['sharpen']);
     // cnFormatting::toBoolean( $atts['crop'] );
     cnFormatting::toBoolean($atts['crop_only']);
     $atts['sizes'] = explode('|', $atts['sizes']);
     array_map('trim', $atts['sizes']);
     array_map('absint', $atts['sizes']);
     if (empty($atts['sizes'])) {
         return __('No image sizes were supplied or supplied values were invalid.', 'connections');
     }
     switch ($atts['type']) {
         case 'attachment':
             $source = wp_get_attachment_url(absint($atts['source']));
             break;
         case 'featured':
             $source = wp_get_attachment_url(get_post_thumbnail_id());
             break;
         case 'path':
             $source = $atts['source'];
             break;
         case 'url':
             $source = esc_url($atts['source']);
             break;
         case 'logo':
             $result = $instance->retrieve->entry(absint($atts['source']));
             $entry = new cnEntry($result);
             $meta = $entry->getImageMeta(array('type' => 'logo'));
             if (is_wp_error($meta)) {
                 // Display the error messages.
                 return implode(PHP_EOL, $meta->get_error_messages());
             }
             $source = $meta['url'];
             break;
         case 'photo':
             $result = $instance->retrieve->entry(absint($atts['source']));
             $entry = new cnEntry($result);
             $meta = $entry->getImageMeta(array('type' => 'photo'));
             if (is_wp_error($meta)) {
                 // Display the error messages.
                 return implode(PHP_EOL, $meta->get_error_messages());
             }
             $source = $meta['url'];
             break;
     }
     // Unset $atts['source'] because passing that $atts to cnImage::get() extracts and overwrite the $source var.
     unset($atts['source']);
     foreach ($atts['sizes'] as $width) {
         $atts['width'] = $width;
         $image = cnImage::get($source, $atts, 'data');
         if (is_wp_error($image)) {
             // Display the error messages.
             return implode(PHP_EOL, $image->get_error_messages());
         } elseif ($image === FALSE) {
             return __('An error has occured while creating the thumbnail.', 'connections');
         }
         if (defined('WP_DEBUG') && WP_DEBUG === TRUE) {
             $log[] = '<pre>' . $image['log'] . '</pre>';
         }
         $srcset[] = $image['url'] . ' ' . $width . 'w';
     }
     $out = sprintf('<img class="cn-image" srcset="%1$s" sizes="100vw"%2$s />', implode(',', $srcset), empty($content) ? '' : ' alt="' . esc_attr($content) . '"');
     if (defined('WP_DEBUG') && WP_DEBUG === TRUE) {
         $out .= implode('', $log);
     }
     return $out;
 }
/**
 * Display the upcoming list.
 *
 * @access public
 * @since  unknown
 *
 * @param array  $atts
 * @param string $content [optional]
 * @param string $tag     [optional] When called as the callback for add_shortcode, the shortcode tag is passed
 *                        automatically. Manually setting the shortcode tag so the function can be called
 *                        independently.
 *
 * @return string
 */
function _upcoming_list($atts, $content = NULL, $tag = 'upcoming_list')
{
    global $connections, $wpdb;
    // $template =& $connections->template;
    $out = '';
    $alternate = '';
    $atts = shortcode_atts(array('list_type' => 'birthday', 'days' => '30', 'include_today' => TRUE, 'private_override' => FALSE, 'date_format' => 'F jS', 'show_lastname' => FALSE, 'show_title' => TRUE, 'list_title' => NULL, 'template' => NULL), $atts, $tag);
    /*
     * Convert some of the $atts values in the array to boolean.
     */
    cnFormatting::toBoolean($atts['include_today']);
    cnFormatting::toBoolean($atts['private_override']);
    cnFormatting::toBoolean($atts['show_lastname']);
    cnFormatting::toBoolean($atts['repeat_alphaindex']);
    cnFormatting::toBoolean($atts['show_title']);
    /*
     * If a list type was specified in the shortcode, load the template based on that type.
     * However, if a specific template was specified, that should preempt the template to be loaded based on the list type if it was specified..
     */
    if (!empty($atts['template'])) {
        $template = cnTemplateFactory::getTemplate($atts['template']);
    } else {
        $templateSlug = $connections->options->getActiveTemplate($atts['list_type']);
        $template = cnTemplateFactory::getTemplate($templateSlug);
    }
    // No template found return error message.
    if ($template == FALSE) {
        return '<p style="color:red; font-weight:bold; text-align:center;">' . sprintf(__('ERROR: Template %1$s not found.', 'connections'), $atts['template']) . '</p>';
    }
    do_action('cn_template_include_once-' . $template->getSlug());
    do_action('cn_template_enqueue_js-' . $template->getSlug());
    /*
     * Set the query vars and run query.
     */
    // Show only public or private [if permitted] entries.
    if (is_user_logged_in() || $atts['private_override'] != FALSE) {
        $visibilityfilter = " AND (visibility='private' OR visibility='public') AND (" . $atts['list_type'] . " != '')";
    } else {
        $visibilityfilter = " AND (visibility='public') AND (`" . $atts['list_type'] . "` != '')";
    }
    // Get the current date from WP which should have the current time zone offset.
    $wpCurrentDate = date('Y-m-d', $connections->options->wpCurrentTime);
    // Whether or not to include the event occurring today or not.
    $atts['include_today'] ? $includeToday = '<=' : ($includeToday = '<');
    $newSQL = "SELECT * FROM " . CN_ENTRY_TABLE . " WHERE" . "  (YEAR(DATE_ADD('{$wpCurrentDate}', INTERVAL " . $atts['days'] . " DAY))" . " - YEAR(DATE_ADD(FROM_UNIXTIME(`" . $atts['list_type'] . "`), INTERVAL " . $connections->options->sqlTimeOffset . " SECOND)) )" . " - ( MID(DATE_ADD('{$wpCurrentDate}', INTERVAL " . $atts['days'] . " DAY),5,6)" . " < MID(DATE_ADD(FROM_UNIXTIME(`" . $atts['list_type'] . "`), INTERVAL " . $connections->options->sqlTimeOffset . " SECOND),5,6) )" . " > ( YEAR('{$wpCurrentDate}')" . " - YEAR(DATE_ADD(FROM_UNIXTIME(`" . $atts['list_type'] . "`), INTERVAL " . $connections->options->sqlTimeOffset . " SECOND)) )" . " - ( MID('{$wpCurrentDate}',5,6)" . " " . $includeToday . " MID(DATE_ADD(FROM_UNIXTIME(`" . $atts['list_type'] . "`), INTERVAL " . $connections->options->sqlTimeOffset . " SECOND),5,6) )" . $visibilityfilter;
    //$out .= print_r($newSQL , TRUE);
    $results = $wpdb->get_results($newSQL);
    //$out .= print_r($results , TRUE);
    // If there are no results no need to proceed and output message.
    if (empty($results)) {
        $noResultMessage = __('No results.', 'connections');
        $noResultMessage = apply_filters('cn_upcoming_no_result_message', $noResultMessage);
        $out .= '<p class="cn-upcoming-no-results">' . $noResultMessage . '</p>';
    } else {
        /*The SQL returns an array sorted by the birthday and/or anniversary date. However the year end wrap needs to be accounted for.
        		Otherwise earlier months of the year show before the later months in the year. Example Jan before Dec. The desired output is to show
        		Dec then Jan dates.  This function checks to see if the month is a month earlier than the current month. If it is the year is changed to the following year rather than the current.
        		After a new list is built, it is resorted based on the date.*/
        foreach ($results as $key => $row) {
            if (gmmktime(23, 59, 59, gmdate('m', $row->{$atts}['list_type']), gmdate('d', $row->{$atts}['list_type']), gmdate('Y', $connections->options->wpCurrentTime)) < $connections->options->wpCurrentTime) {
                $dateSort[] = $row->{$atts}['list_type'] = gmmktime(0, 0, 0, gmdate('m', $row->{$atts}['list_type']), gmdate('d', $row->{$atts}['list_type']), gmdate('Y', $connections->options->wpCurrentTime) + 1);
            } else {
                $dateSort[] = $row->{$atts}['list_type'] = gmmktime(0, 0, 0, gmdate('m', $row->{$atts}['list_type']), gmdate('d', $row->{$atts}['list_type']), gmdate('Y', $connections->options->wpCurrentTime));
            }
        }
        array_multisort($dateSort, SORT_ASC, $results);
        if (empty($atts['list_title'])) {
            switch ($atts['list_type']) {
                case 'birthday':
                    if ($atts['days'] >= 1) {
                        $list_title = 'Upcoming Birthdays the next ' . $atts['days'] . ' days';
                    } else {
                        $list_title = 'Today\'s Birthdays';
                    }
                    break;
                case 'anniversary':
                    if ($atts['days'] >= 1) {
                        $list_title = 'Upcoming Anniversaries the next ' . $atts['days'] . ' days';
                    } else {
                        $list_title = 'Today\'s Anniversaries';
                    }
                    break;
            }
        } else {
            $list_title = $atts['list_title'];
        }
        ob_start();
        // Prints the template's CSS file.
        do_action('cn_template_inline_css-' . $template->getSlug(), $atts);
        $out .= ob_get_contents();
        ob_end_clean();
        $out .= '<div class="connections-list cn-upcoming cn-' . $atts['list_type'] . '" id="cn-list" data-connections-version="' . $connections->options->getVersion() . '-' . $connections->options->getDBVersion() . '">' . "\n";
        $out .= "\n" . '<div class="cn-template cn-' . $template->getSlug() . '" id="cn-' . $template->getSlug() . '">' . "\n";
        $out .= "\n" . '<div class="cn-clear" id="cn-list-head">' . "\n";
        if ($atts['show_title']) {
            $out .= '<div class="cn-upcoming-title">' . $list_title . '</div>';
        }
        $out .= "\n" . '</div>' . "\n";
        $out .= '<div class="cn-clear" id="cn-list-body">' . "\n";
        foreach ($results as $row) {
            $entry = new cnvCard($row);
            $vCard =& $entry;
            $entry->name = '';
            $alternate == '' ? $alternate = '-alternate' : ($alternate = '');
            /*
             * Whether or not to show the last name.
             * Setting $entry->name is for compatibility to versions prior to 0.7.1.6
             */
            !$atts['show_lastname'] ? $entry->name = $entry->getFirstName() : ($entry->name = $entry->getFullFirstLastName());
            if (!$atts['show_lastname']) {
                $entry->setLastName('');
            }
            $out .= '<div class="cn-upcoming-row' . $alternate . ' vcard ' . '">' . "\n";
            ob_start();
            do_action('cn_action_card-' . $template->getSlug(), $entry, $template, $atts);
            $out .= ob_get_contents();
            ob_end_clean();
            $out .= '</div>' . "\n";
        }
        $out .= "\n" . '</div>' . "\n";
        $out .= "\n" . '<div class="cn-clear" id="cn-list-foot">' . "\n";
        $out .= "\n" . '</div>' . "\n";
        $out .= "\n" . '</div>' . "\n";
        $out .= "\n" . '</div>' . "\n";
    }
    if (cnSettingsAPI::get('connections', 'connections_compatibility', 'strip_rnt')) {
        $search = array("\r\n", "\r", "\n", "\t");
        $replace = array('', '', '', '');
        $out = str_replace($search, $replace, $out);
    }
    return $out;
}
Example #4
0
/** @since version 0.7.1.0 */
function _connections_list($atts, $content = null)
{
    global $wpdb, $connections, $current_user;
    $form = new cnFormObjects();
    $convert = new cnFormatting();
    $format =& $convert;
    $template = new stdClass();
    $atts = shortcode_atts(array('id' => NULL, 'category' => NULL, 'exclude_category' => NULL, 'category_name' => NULL, 'wp_current_category' => 'false', 'allow_public_override' => 'false', 'private_override' => 'false', 'show_alphaindex' => 'false', 'repeat_alphaindex' => 'false', 'show_alphahead' => 'false', 'list_type' => NULL, 'limit' => NULL, 'offset' => NULL, 'order_by' => NULL, 'group_name' => NULL, 'last_name' => NULL, 'title' => NULL, 'organization' => NULL, 'department' => NULL, 'city' => NULL, 'state' => NULL, 'zip_code' => NULL, 'country' => NULL, 'template' => NULL, 'template_name' => NULL), $atts);
    /*
     * Convert some of the $atts values in the array to boolean.
     */
    $convert->toBoolean(&$atts['allow_public_override']);
    $convert->toBoolean(&$atts['private_override']);
    $convert->toBoolean(&$atts['show_alphaindex']);
    $convert->toBoolean(&$atts['repeat_alphaindex']);
    $convert->toBoolean(&$atts['show_alphahead']);
    $convert->toBoolean(&$atts['wp_current_category']);
    $permittedListTypes = array('individual', 'organization', 'family', 'connection_group');
    // Convert the supplied entry types $atts['list_type'] to an array.
    if (!empty($atts['list_type'])) {
        // Trim the space characters if present.
        $atts['list_type'] = str_replace(' ', '', $atts['list_type']);
        // Convert to array.
        $atts['list_type'] = explode(',', $atts['list_type']);
    }
    // Set the template type to the first in the entry type from the supplied if multiple list types are provided.
    if (!empty($atts['list_type']) && (bool) array_intersect((array) $atts['list_type'], $permittedListTypes)) {
        $templateType = $atts['list_type'][0];
    }
    /*
     * As of version 0.7.0.5 the $atts['template_name'] is deprecated.
     */
    if (isset($atts['template_name'])) {
        // First check to see if the template is in the custom template folder.
        if (is_dir(CN_CUSTOM_TEMPLATE_PATH) && is_readable(CN_CUSTOM_TEMPLATE_PATH)) {
            if (file_exists(CN_CUSTOM_TEMPLATE_PATH . '/' . $atts['template_name'] . '.php')) {
                $template->file = CN_CUSTOM_TEMPLATE_PATH . '/' . $atts['template_name'] . '.php';
            }
        }
        // If the template is not in the custom template folder, check for it in the default template folder.
        if (!isset($template->file)) {
            if (file_exists(CN_BASE_PATH . '/templates/' . $atts['template_name'] . '.php')) {
                $template->file = CN_BASE_PATH . '/templates/' . $atts['template_name'] . '.php';
            }
        }
    } else {
        $template = new cnTemplate();
        // Change the list type to family from connection_group to maintain compatibility with versions .0.7.0.4 and earlier.
        if ($atts['list_type'] === 'connection_group') {
            $atts['list_type'] = 'family';
        }
        /*
         * $atts['template'] can be either a string or an object. It is a string when set
         * with the shortcode attribute. If it is a string, the template will be loaded
         * via the cnTemplate class.
         * 
         * If the attribute is not set, it will be the object returned from the
         * cnOptions::getActiveTemplate() method which stores the default template
         * per list style.
         */
        if (isset($atts['template']) && !is_object($atts['template'])) {
            $template->load($atts['template']);
            $template->includeFunctions();
        } else {
            if (empty($templateType)) {
                $templateType = 'all';
            }
            // If no list type was specified, set the default ALL template.
            $template->init($connections->options->getActiveTemplate($templateType));
            $template->includeFunctions();
        }
    }
    // If no template is found, return an error message.
    if (!isset($template->file)) {
        return '<p style="color:red; font-weight:bold; text-align:center;">ERROR: Template "' . $atts['template_name'] . $atts['template'] . '" not found.</p>';
    }
    $atts = apply_filters('cn_list_atts', $atts);
    $results = $connections->retrieve->entries($atts);
    //print_r($connections->lastQuery);
    if (!empty($results)) {
        $results = apply_filters('cn_list_results', $results);
    }
    // Prints the template's CSS file.
    if (method_exists($template, 'printCSS')) {
        $out .= $template->printCSS();
    }
    // Prints the javascript tag in the footer if $template->js path is set
    if (method_exists($template, 'printJS')) {
        $template->printJS();
    }
    $out = apply_filters('cn_list_before', $out, $results);
    // If there are no results no need to proceed and output message.
    if (empty($results)) {
        $noResultMessage = 'No results';
        $noResultMessage = apply_filters('cn_no_result_message', $noResultMessage);
        return $out . '<p class="cn-no-results">' . $noResultMessage . '</p>';
    }
    $out .= '<a name="connections-list-head" style="float: left;"></a>' . "\n";
    /*
     * The alpha index is only displayed if set set to true and not set to repeat using the shortcode attributes.
     * If a alpha index is set to repeat, that is handled down separately.
     */
    if ($atts['show_alphaindex'] && !$atts['repeat_alphaindex']) {
        $index = "<div class='cn-alphaindex' style='text-align:right;font-size:larger;font-weight:bold'>" . $form->buildAlphaIndex() . "</div>";
        $out .= apply_filters('cn_list_index', $index, $results);
    }
    $out .= '<div class="connections-list">' . "\n";
    foreach ((array) $results as $row) {
        //$entry = new cnOutput($row);
        $entry = new cnvCard($row);
        //$vCard = new cnvCard($row);
        $vCard =& $entry;
        if (isset($continue)) {
            unset($continue);
        }
        if (isset($cities)) {
            unset($cities);
        }
        if (isset($states)) {
            unset($states);
        }
        if (isset($zipcodes)) {
            unset($zipcodes);
        }
        if (isset($countries)) {
            unset($countries);
        }
        if (isset($setAnchor)) {
            unset($setAnchor);
        }
        /*
         * Check to make sure there is data stored in the address array.
         * Cycle thru each address, building separate arrays for city, state, zip and country.
         */
        if ($entry->getAddresses()) {
            foreach ($entry->getAddresses() as $address) {
                if ($address->city != NULL) {
                    $cities[] = $address->city;
                }
                if ($address->state != NULL) {
                    $states[] = $address->state;
                }
                if ($address->zipcode != NULL) {
                    $zipcodes[] = $address->zipcode;
                }
                if ($address->country != NULL) {
                    $countries[] = $address->country;
                }
            }
        }
        /*
         * Filter out the entries that are wanted based on the
         * filter attributes that may have been used in the shortcode.
         * 
         * NOTE: The '@' operator is used to suppress PHP generated errors. This is done
         * because not every entry will have addresses to populate the arrays created above.
         * 
         * NOTE: Since the entry class returns all fields escaped, the shortcode filter
         * attribute needs to be escaped as well so the comparason between the two functions
         * as expected.
         */
        $atts['group_name'] = esc_attr($atts['group_name']);
        $atts['last_name'] = esc_attr($atts['last_name']);
        $atts['title'] = esc_attr($atts['title']);
        $atts['organization'] = esc_attr($atts['organization']);
        $atts['department'] = esc_attr($atts['department']);
        if ($entry->getFamilyName() != $atts['group_name'] && $atts['group_name'] != null) {
            $continue = true;
        }
        if ($entry->getLastName() != $atts['last_name'] && $atts['last_name'] != null) {
            $continue = true;
        }
        if ($entry->getTitle() != $atts['title'] && $atts['title'] != null) {
            $continue = true;
        }
        if ($entry->getOrganization() != $atts['organization'] && $atts['organization'] != null) {
            $continue = true;
        }
        if ($entry->getDepartment() != $atts['department'] && $atts['department'] != null) {
            $continue = true;
        }
        if (@(!in_array($atts['city'], $cities)) && $atts['city'] != null) {
            $continue = true;
        }
        if (@(!in_array($atts['state'], $states)) && $atts['state'] != null) {
            $continue = true;
        }
        if (@(!in_array($atts['zip_code'], $zipcodes)) && $atts['zip_code'] != null) {
            $continue = true;
        }
        if (@(!in_array($atts['country'], $countries)) && $atts['country'] != null) {
            $continue = true;
        }
        /*
         * If any of the above filters returned true, the script will continue to the next entry.
         */
        if ($continue == true) {
            continue;
        }
        /*
         * Checks the first letter of the last name to see if it is the next
         * letter in the alpha array and sets the anchor.
         * 
         * If the alpha index is set to repeat it will append to the anchor.
         * 
         * If the alpha head set to true it will append the alpha head to the anchor.
         */
        $currentLetter = strtoupper(mb_substr($entry->getSortColumn(), 0, 1));
        if ($currentLetter != $previousLetter && $atts['id'] == null) {
            if ($atts['show_alphaindex']) {
                $setAnchor = '<a class="cn-index-head" name="' . $currentLetter . '"></a>';
            }
            if ($atts['show_alphaindex'] && $atts['repeat_alphaindex']) {
                $setAnchor .= "<div class='cn-alphaindex' style='text-align:right;font-size:larger;font-weight:bold'>" . $form->buildAlphaIndex() . "</div>";
            }
            if ($atts['show_alphahead']) {
                $setAnchor .= '<h4 class="cn-alphahead">' . $currentLetter . '</h4>';
            }
            $previousLetter = $currentLetter;
        } else {
            $setAnchor = null;
        }
        /*
         * The anchor and/or the alpha head is displayed if set to true using the shortcode attributes.
         */
        if ($atts['show_alphaindex'] || $atts['show_alphahead']) {
            $out .= $setAnchor;
        }
        $alternate == '' ? $alternate = '-alternate' : ($alternate = '');
        $out .= '<div class="cn-list-row' . $alternate . ' vcard ' . $template->slug . ' ' . $entry->getCategoryClass(TRUE) . '">' . "\n";
        $out = apply_filters('cn_entry_before', $out, $entry);
        ob_start();
        include $template->file;
        $out .= ob_get_contents();
        ob_end_clean();
        $out = apply_filters('cn_entry_after', $out, $entry);
        $out .= '</div>' . "\n";
    }
    $out .= '<div class="clear"></div>' . "\n";
    $out .= '</div>' . "\n";
    $out = apply_filters('cn_list_after', $out, $results);
    return $out;
}