/** * Initiate the template options using the option values. * * @access private * @since 3.0 * * @param array $atts The shortcode $atts array. * * @return array */ public static function initOptions($atts) { if (cnQuery::getVar('cn-entry-slug')) { /** * @var cnOutput $entry * @var array $option */ $options = cnSettingsAPI::get('connections_template', self::SLUG, 'single'); } else { /** * @var cnOutput $entry * @var array $option */ $options = cnSettingsAPI::get('connections_template', self::SLUG, 'card'); $style = array('background-color' => '#FFF', 'border' => $options['border_width'] . 'px solid ' . $options['border_color'], 'border-radius' => $options['border_radius'] . 'px', 'color' => '#000', 'margin' => '8px 0', 'padding' => '10px', 'position' => 'relative'); if (is_array($style)) { $atts = wp_parse_args($style, $atts); } } if (is_array($options)) { $atts = wp_parse_args($options, $atts); } return $atts; }
/** * Create a permalink. * * @todo Should check to ensure require params are set and valid and pass back WP_Error if they are not. * @todo The type case statement should have a default with an filter attached so this can be pluggable. * * NOTE: When the `name` permalink is being requested, use the entry slug. * It is saved id the db as URL encoded. If any other strings pass * for the `name` permalink must be URL encoded. * All the other permalink types will be URL encoded in this method * so pass stings without URL encoding. * * @access private * @since 0.7.3 * @static * * @global $wp_rewrite * @global $post * * @uses is_admin() * @uses wp_parse_args() * @uses get_option() * @uses in_the_loop() * @uses is_page() * @uses trailingslashit() * @uses get_permalink() * @uses add_query_arg() * @uses is_front_page() * * @param array $atts { * Optional. An array of arguments. * * @type string $class The class to give the anchor. * Default: '' * @type string $text The anchor text. * Default: '' * @type string $title The anchor title attribute. * Default: '' * @type bool $follow Whether or not the anchor rel should be follow or nofollow * Default: TRUE * @type string $rel The rel attribute. * Default: '' * @type string $slug The slug of the object to build the permalink for. ie. the entry slug or term slug. * Default: '' * @type string $on_click The inline javascript on_click attribute. * Default: '' * @type string $type The type of permalink to create. ie. name, edit, home * Default: 'name' * @type int $home_id The page ID of the directory home. * Default: The page set as the Directory Home Page. * @type bool $force_home Whether or not to for the page ID to the page ID of the page set as the Directory Home Page. * Default: FALSE * @type string $data What to return. * Default: tag * Accepts: tag | url * @type bool $return Whether or not to return or echo the permalink. * Default: FALSE * } * * @return string */ public static function permalink($atts) { /** @var $wp_rewrite WP_Rewrite */ global $wp_rewrite, $post; // The class.seo.file is only loaded in the frontend; do not attempt to remove the filter // otherwise it'll cause an error. if (!is_admin()) { cnSEO::doFilterPermalink(FALSE); } // The anchor attributes. $piece = array(); $defaults = array('class' => '', 'text' => '', 'title' => '', 'follow' => TRUE, 'rel' => '', 'slug' => '', 'on_click' => '', 'type' => 'name', 'home_id' => cnSettingsAPI::get('connections', 'connections_home_page', 'page_id'), 'force_home' => FALSE, 'data' => 'tag', 'return' => FALSE); $atts = wp_parse_args($atts, $defaults); // Get the directory home page ID. $homeID = $atts['force_home'] ? cnSettingsAPI::get('connections', 'connections_home_page', 'page_id') : $atts['home_id']; // Get the settings for the base of each data type to be used in the URL. $base = get_option('connections_permalink'); // Create the permalink base based on context where the entry is being displayed. if (in_the_loop() && is_page()) { if ($wp_rewrite->using_permalinks()) { // Only slash it when using pretty permalinks. $permalink = trailingslashit(get_permalink($homeID)); } else { $permalink = get_permalink($homeID); // If the current page is the front page, the `page_id` query var must be added because without it, WP // will redirect to the blog/posts home page. if (is_front_page()) { $permalink = add_query_arg('page_id', $post->ID, $permalink); } } } else { // If using pretty permalinks get the directory home page ID and slash it, otherwise just add the page_id to the query string. if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit(get_permalink($homeID)); } else { $permalink = add_query_arg(array('page_id' => $homeID, 'p' => FALSE), get_permalink($homeID)); } } if (!empty($atts['class'])) { $piece['class'] = 'class="' . $atts['class'] . '"'; } // if ( ! empty( $atts['slug'] ) ) $piece['id'] = 'id="' . $atts['slug'] .'"'; if (!empty($atts['title'])) { $piece['title'] = 'title="' . $atts['title'] . '"'; } if (!empty($atts['target'])) { $piece['target'] = 'target="' . $atts['target'] . '"'; } if (!$atts['follow']) { $piece['follow'] = 'rel="nofollow"'; } if (!empty($atts['rel'])) { $piece['rel'] = 'rel="' . $atts['rel'] . '"'; } if (!empty($atts['on_click'])) { $piece['on_click'] = 'onClick="' . $atts['on_click'] . '"'; } switch ($atts['type']) { case 'home': break; case 'all': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . 'view/all/'); } else { $permalink = add_query_arg('cn-view', 'all', $permalink); } break; case 'submit': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . 'submit/'); } else { $permalink = add_query_arg('cn-view', 'submit', $permalink); } break; case 'edit': if ($wp_rewrite->using_permalinks()) { // The entry slug is saved in the db urlencoded so we'll expect when the permalink for entry name is // requested that the entry slug is being used so urlencode() will not be use as not to double encode it. $permalink = trailingslashit($permalink . $base['name_base'] . '/' . $atts['slug'] . '/edit'); } else { $permalink = add_query_arg(array('cn-entry-slug' => $atts['slug'], 'cn-view' => 'detail', 'cn-process' => 'edit'), $permalink); } break; case 'name': if ($wp_rewrite->using_permalinks()) { // The entry slug is saved in the db urlencoded so we'll expect when the permalink for entry name is // requested that the entry slug is being used so urlencode() will not be use as not to double encode it. $permalink = trailingslashit($permalink . $base['name_base'] . '/' . $atts['slug']); } else { $permalink = add_query_arg(array('cn-entry-slug' => $atts['slug'], 'cn-view' => 'detail'), $permalink); } break; case 'detail': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['name_base'] . '/' . $atts['slug'] . '/detail'); } else { $permalink = add_query_arg(array('cn-entry-slug' => $atts['slug'], 'cn-view' => 'detail'), $permalink); } break; case 'department': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['department_base'] . '/' . urlencode($atts['slug'])); } else { $permalink = add_query_arg('cn-department', urlencode($atts['slug']), $permalink); } break; case 'organization': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['organization_base'] . '/' . urlencode($atts['slug'])); } else { $permalink = add_query_arg('cn-organization', urlencode($atts['slug']), $permalink); } break; case 'category': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['category_base'] . '/' . $atts['slug']); } else { $permalink = add_query_arg('cn-cat-slug', $atts['slug'], $permalink); } break; case 'district': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['district_base'] . '/' . urlencode($atts['slug'])); } else { $permalink = add_query_arg('cn-district', urlencode($atts['slug']), $permalink); } break; case 'county': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['county_base'] . '/' . urlencode($atts['slug'])); } else { $permalink = add_query_arg('cn-county', urlencode($atts['slug']), $permalink); } break; case 'locality': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['locality_base'] . '/' . urlencode($atts['slug'])); } else { $permalink = add_query_arg('cn-locality', urlencode($atts['slug']), $permalink); } break; case 'region': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['region_base'] . '/' . urlencode($atts['slug'])); } else { $permalink = add_query_arg('cn-region', urlencode($atts['slug']), $permalink); } break; case 'postal_code': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['postal_code_base'] . '/' . urlencode($atts['slug'])); } else { $permalink = add_query_arg('cn-postal-code', urlencode($atts['slug']), $permalink); } break; case 'country': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['country_base'] . '/' . urlencode($atts['slug'])); } else { $permalink = add_query_arg('cn-country', urlencode($atts['slug']), $permalink); } break; case 'character': if ($wp_rewrite->using_permalinks()) { $permalink = trailingslashit($permalink . $base['character_base'] . '/' . urlencode($atts['slug'])); } else { $permalink = add_query_arg(array('cn-char' => urlencode($atts['slug'])), $permalink); } break; default: if (has_filter("cn_permalink-{$atts['type']}")) { /** * Allow extensions to add custom permalink types. * * The variable portion of the filter name if the permalink type being created. * * @since 8.5.17 * * @param string $permalink The permalink. * @param array $atts The attributes array. */ $permalink = apply_filters("cn_permalink-{$atts['type']}", $permalink, $atts); } break; } $permalink = apply_filters('cn_permalink', $permalink, $atts); if ('url' == $atts['data']) { $out = esc_url($permalink); } else { $piece['href'] = 'href="' . esc_url($permalink) . '"'; $out = '<a ' . implode(' ', $piece) . '>' . $atts['text'] . '</a>'; } // The class.seo.file is only loaded in the frontend; do not attempt to add the filter // otherwise it'll cause an error. if (!is_admin()) { cnSEO::doFilterPermalink(TRUE); } if ($atts['return']) { return $out; } echo $out; }
/** * Renders the Template admin page. * * @access private * @since unknown */ function connectionsShowTemplatesPage() { /* * Check whether user can edit Settings */ if (!current_user_can('connections_manage_template')) { wp_die('<p id="error-page" style="-moz-background-clip:border; -moz-border-radius:11px; background:#FFFFFF none repeat scroll 0 0; border:1px solid #DFDFDF; color:#333333; display:block; font-size:12px; line-height:18px; margin:25px auto 20px; padding:1em 2em; text-align:center; width:700px">' . __('You do not have sufficient permissions to access this page.', 'connections') . '</p>'); } else { // Grab an instance of the Connections object. $instance = Connections_Directory(); $type = isset($_GET['type']) ? esc_attr($_GET['type']) : 'all'; $templates = cnTemplateFactory::getCatalog($type); $adminURL = self_admin_url('admin.php'); $pageURL = add_query_arg('page', 'connections_templates', $adminURL); $homeID = cnSettingsAPI::get('connections', 'connections_home_page', 'page_id'); $homeURL = get_permalink($homeID); $customizerURL = add_query_arg('cn-customize-template', 'true', $homeURL); ?> <div class="wrap"> <h1>Connections : <?php _e('Templates', 'connections'); ?> <a class="button add-new-h2" href="http://connections-pro.com/templates/" target="_blank"><?php _e('Get More', 'connections'); ?> </a> </h1> <ul class="subsubsub"> <li> <a <?php if ('all' == $type) { echo 'class="current" '; } ?> href="<?php echo esc_url(add_query_arg('type', 'all', $pageURL)); ?> "> <?php _e('All', 'connections'); ?> </a> | </li> <li> <a <?php if ('individual' == $type) { echo 'class="current" '; } ?> href="<?php echo esc_url(add_query_arg('type', 'individual', $pageURL)); ?> "> <?php _e('Individual', 'connections'); ?> </a> | </li> <li> <a <?php if ('organization' == $type) { echo 'class="current" '; } ?> href="<?php echo esc_url(add_query_arg('type', 'organization', $pageURL)); ?> "> <?php _e('Organization', 'connections'); ?> </a> | </li> <li> <a <?php if ('family' == $type) { echo 'class="current" '; } ?> href="<?php echo esc_url(add_query_arg('type', 'family', $pageURL)); ?> "> <?php _e('Family', 'connections'); ?> </a> | </li> <li> <a <?php if ('anniversary' == $type) { echo 'class="current" '; } ?> href="<?php echo esc_url(add_query_arg('type', 'anniversary', $pageURL)); ?> "> <?php _e('Anniversary', 'connections'); ?> </a> | </li> <li> <a <?php if ('birthday' == $type) { echo 'class="current" '; } ?> href="<?php echo esc_url(add_query_arg('type', 'birthday', $pageURL)); ?> "> <?php _e('Birthday', 'connections'); ?> </a> </li> </ul> <br class="clear"> <table cellspacing="0" cellpadding="0" id="currenttheme"> <tbody> <tr> <td class="current_template"> <h2><?php _e('Current Template', 'connections'); ?> </h2> <div id="current-template"> <?php $slug = $instance->options->getActiveTemplate($type); /** @var cnTemplate $activeTemplate */ $activeTemplate = cnTemplateFactory::getTemplate($slug); if ($activeTemplate) { cnTemplateThumbnail($activeTemplate); cnTemplateAuthor($activeTemplate); cnTemplateDescription($activeTemplate); cnTemplateCustomizerButton($activeTemplate, $customizerURL, $pageURL); // Remove the current template so it does not show in the available templates. unset($templates->{$activeTemplate->getSlug()}); } else { echo '<h3 class="error"> Template ', esc_attr($slug), ' can not be found.</h3>'; } ?> </div> <div class="clear"></div> </td> <td class="template_instructions" colspan="2"> <p> <strong><?php _e('Instructions', 'connections'); ?> :</strong> </p> <p> <?php _e('By default the <code><a href="http://connections-pro.com/documentation/connections/shortcodes/shortcode-connections/">[connections]</a></code> shortcode will show all entries types. To change the template used when displaying all entry types, select the "All" tab and activate the template. When the <code><a href="http://connections-pro.com/documentation/connections/shortcodes/shortcode-connections/list_type/">list_type</a></code>shortcode option is used to filter the entries based on the entry type, the template for that entry type will be used. To change the template used for a specific entry type, select the appropriate tab and then activate the template. If multiple entry types are specified in the <code><a href="http://connections-pro.com/documentation/connections/shortcodes/shortcode-connections/list_type/">list_type</a></code> shortcode option, the template for the entry type listed first will be used to display the entry list.', 'connections'); ?> </p> <p> <?php _e('The <code><a href="http://connections-pro.com/documentation/connections/shortcodes/shortcode-upcoming-list/">[upcoming_list]</a></code> shortcode which displays the upcoming anniversaries and birthdays will be displayed with the template that is activated under their respective tabs.', 'connections'); ?> </p> <p> <?php _e('The current active template for each template type can be overridden by using the <code><a href="http://connections-pro.com/documentation/connections/shortcodes/shortcode-connections/template-option/">template</a></code> shortcode option.', 'connections'); ?> </p> </td> </tr> </tbody> </table> <!-- /#currenttheme --> <table cellspacing="0" cellpadding="0" id="availablethemes"> <tbody> <tr> <td class="current_template" colspan="3"> <h2><?php _e('Available Templates', 'connections'); ?> </h2> </td> </tr> <?php $slugs = array_keys((array) $templates); natcasesort($slugs); $table = array(); $rows = ceil(count($slugs) / 3); for ($row = 1; $row <= $rows; $row++) { for ($col = 1; $col <= 3; $col++) { $table[$row][$col] = array_shift($slugs); } } foreach ($table as $row => $cols) { ?> <tr> <?php foreach ($cols as $col => $slug) { if (!isset($templates->{$slug})) { continue; } /** @var cnTemplate $template */ $template = $templates->{$slug}; $class = array('available-theme'); if ($row == 1) { $class[] = 'top'; } if ($row == $rows) { $class[] = 'bottom'; } if ($col == 1) { $class[] = 'left'; } if ($col == 3) { $class[] = 'right'; } ?> <td <?php echo cnHTML::attribute('class', $class); ?> > <?php cnTemplateThumbnail($template); cnTemplateAuthor($template); cnTemplateDescription($template); cnTemplateDeactivateText($template); cnTemplateShortcodeOverride($template); ?> <span class="action-links"> <?php cntemplateActivateButton($template, $type); cnTemplateDeleteButton($template); cnTemplateCustomizerButton($template, $customizerURL, $pageURL); ?> </span> </td> <?php } ?> </tr> <?php } ?> </tbody> </table> <!-- /#availablethemes --> </div> <!-- /.wrap --> <?php } }
/** * Return an array of entry ID/s found with the supplied search terms. * * @todo Allow the fields for each table to be defined as a comma delimited list, convert an array and validate against of list of valid table fields. * @todo Add a filter to allow the search fields to be changed. * * Resources used: * http://devzone.zend.com/26/using-mysql-full-text-searching/ * http://onlamp.com/onlamp/2003/06/26/fulltext.html * * @since 0.7.2.0 * @param array $atts [optional] * * @return array */ public function search($atts = array()) { /** @var wpdb $wpdb */ global $wpdb; // Grab an instance of the Connections object. $instance = Connections_Directory(); $results = array(); $scored = array(); $fields = $instance->options->getSearchFields(); $fields = apply_filters('cn_search_fields', $fields); // If no search search fields are set, return an empty array. if (empty($fields)) { return array(); } /* * // START -- Set the default attributes array. \\ */ $defaults['terms'] = array(); if (in_array('family_name', $fields)) { $defaults['fields']['entry'][] = 'family_name'; } if (in_array('first_name', $fields)) { $defaults['fields']['entry'][] = 'first_name'; } if (in_array('middle_name', $fields)) { $defaults['fields']['entry'][] = 'middle_name'; } if (in_array('last_name', $fields)) { $defaults['fields']['entry'][] = 'last_name'; } if (in_array('title', $fields)) { $defaults['fields']['entry'][] = 'title'; } if (in_array('organization', $fields)) { $defaults['fields']['entry'][] = 'organization'; } if (in_array('department', $fields)) { $defaults['fields']['entry'][] = 'department'; } if (in_array('contact_first_name', $fields)) { $defaults['fields']['entry'][] = 'contact_first_name'; } if (in_array('contact_last_name', $fields)) { $defaults['fields']['entry'][] = 'contact_last_name'; } if (in_array('bio', $fields)) { $defaults['fields']['entry'][] = 'bio'; } if (in_array('notes', $fields)) { $defaults['fields']['entry'][] = 'notes'; } if (in_array('address_line_1', $fields)) { $defaults['fields']['address'][] = 'line_1'; } if (in_array('address_line_2', $fields)) { $defaults['fields']['address'][] = 'line_2'; } if (in_array('address_line_3', $fields)) { $defaults['fields']['address'][] = 'line_3'; } if (in_array('address_city', $fields)) { $defaults['fields']['address'][] = 'city'; } if (in_array('address_state', $fields)) { $defaults['fields']['address'][] = 'state'; } if (in_array('address_zipcode', $fields)) { $defaults['fields']['address'][] = 'zipcode'; } if (in_array('address_country', $fields)) { $defaults['fields']['address'][] = 'country'; } if (in_array('phone_number', $fields)) { $defaults['fields']['phone'][] = 'number'; } $atts = wp_parse_args($atts, apply_filters('cn_search_atts', $defaults)); // @todo Validate each fiels array to ensure only permitted fields will be used. /* * // END -- Set the default attributes array if not supplied. \\ */ // If no search terms were entered, return an empty array. if (empty($atts['terms'])) { return array(); } // If value is a string, stripe the white space and covert to an array. if (!is_array($atts['terms'])) { $atts['terms'] = explode(' ', trim($atts['terms'])); } // Trim any white space from around the terms in the array. array_walk($atts['terms'], 'trim'); $atts['terms'] = apply_filters('cn_search_terms', $atts['terms']); // Remove any single characters and stop words from terms. $atts['terms'] = $this->parse_search_terms($atts['terms']); // If no search terms are left after removing stop words, return an empty array. if (empty($atts['terms'])) { return array(); } /* * Perform search using FULLTEXT if enabled. * * Perform the search on each table individually because joining the tables doesn't scale when * there are a large number of entries. * * NOTES: * The following is the error reported by MySQL when DB does not support FULLTEXT: 'The used table type doesn't support FULLTEXT indexes' * If DB does not support FULLTEXT the query will fail and the $results will be an empty array. * * FULLTEXT Restrictions as noted here: http://onlamp.com/onlamp/2003/06/26/fulltext.html * * Some of the default behaviors of these restrictions can be changed in your my.cnf or using the SET command * * FULLTEXT indices are NOT supported in InnoDB tables. * MySQL requires that you have at least three rows of data in your result set before it will return any results. * By default, if a search term appears in more than 50% of the rows then MySQL will not return any results. * By default, your search query must be at least four characters long and may not exceed 254 characters. * MySQL has a default stopwords file that has a list of common words (i.e., the, that, has) which are not returned in your search. In other words, searching for the will return zero rows. * According to MySQL's manual, the argument to AGAINST() must be a constant string. In other words, you cannot search for values returned within the query. */ if (cnSettingsAPI::get('connections', 'search', 'fulltext_enabled')) { $terms = array(); $shortwords = array(); /* * Remove any shortwords from the FULLTEXT query since the db will drop them anyway. * Add the shortwords to a separate array to be used to do a LIKE query. */ foreach ($atts['terms'] as $key => $term) { if (strlen($term) >= 2 && strlen($term) <= 3) { unset($atts['terms'][$key]); $shortwords[] = $term; } } if (!empty($atts['terms'])) { // Make each term required, functional AND query. $terms = apply_filters('cn_search_fulltext_terms', '+' . implode(' +', $atts['terms'])); } /* * Only search the primary records if at least one fields is selected to be searched. */ if (!empty($atts['fields']['entry'])) { $select = array(); $from = array(); $where = array(); $like = array(); $select[] = 'SELECT ' . CN_ENTRY_TABLE . '.id'; /* * Set up the SELECT to return the results scored by relevance. */ if (!empty($terms)) { $select[] = $wpdb->prepare('MATCH (' . implode(', ', $atts['fields']['entry']) . ') AGAINST (%s) AS score', $terms); } $from[] = CN_ENTRY_TABLE; /* * If there are long word terms, perform a FULLTEXT query. */ if (!empty($terms)) { $where[] = $wpdb->prepare('MATCH (' . implode(', ', $atts['fields']['entry']) . ') AGAINST (%s IN BOOLEAN MODE)', $terms); } /* * If there are no long words and there are short words, perform a LIKE query for the short words. */ if (empty($terms) && !empty($shortwords)) { foreach ($shortwords as $word) { $like[] = $wpdb->prepare(implode(' LIKE %s OR ', $atts['fields']['entry']) . ' LIKE %s ', array_fill(0, count($atts['fields']['entry']), $wpdb->esc_like($word) . '%')); } $where[] = '( ' . implode(') OR (', $like) . ')'; } /* * Return the query results ordered by the relevance score. */ $orderBy = empty($terms) ? '' : ' ORDER BY score'; $sql = implode(', ', $select) . ' FROM ' . implode(',', $from) . ' WHERE ' . implode(' AND ', $where) . $orderBy; $scored = $wpdb->get_results($sql, ARRAY_A); } /* * Only search the address records if at least one fields is selected to be searched. */ if (!empty($atts['fields']['address'])) { $select = array(); $from = array(); $where = array(); $like = array(); $select[] = 'SELECT ' . CN_ENTRY_ADDRESS_TABLE . '.entry_id'; /* * Set up the SELECT to return the results scored by relevance. */ if (!empty($terms)) { $select[] = $wpdb->prepare('MATCH (' . implode(', ', $atts['fields']['address']) . ') AGAINST (%s) AS score', $terms); } $from[] = CN_ENTRY_ADDRESS_TABLE; /* * If there are long word terms, perform a FULLTEXT query. */ if (!empty($terms)) { $where[] = $wpdb->prepare('MATCH (' . implode(', ', $atts['fields']['address']) . ') AGAINST (%s IN BOOLEAN MODE)', $terms); } /* * If there are no long words and there are short words, perform a LIKE query for the short words. */ if (empty($terms) && !empty($shortwords)) { foreach ($shortwords as $word) { $like[] = $wpdb->prepare(implode(' LIKE %s OR ', $atts['fields']['address']) . ' LIKE %s ', array_fill(0, count($atts['fields']['address']), $wpdb->esc_like($word) . '%')); } $where[] = '( ' . implode(') OR (', $like) . ')'; } /* * Return the query results ordered by the relevance score. */ $orderBy = empty($terms) ? '' : ' ORDER BY score'; $sql = implode(', ', $select) . ' FROM ' . implode(',', $from) . ' WHERE ' . implode(' AND ', $where) . $orderBy; $ids = $wpdb->get_results($sql, ARRAY_A); /* * If any results are returned merge them in to the $scored results. */ if (!empty($ids)) { $scored = array_merge($scored, $ids); } } /* * Only search the phone records if thefield is selected to be search. */ if (!empty($atts['fields']['phone'])) { $select = array(); $from = array(); $where = array(); $like = array(); $select[] = 'SELECT ' . CN_ENTRY_PHONE_TABLE . '.entry_id'; /* * Set up the SELECT to return the results scored by relevance. */ if (!empty($terms)) { $select[] = $wpdb->prepare('MATCH (' . implode(', ', $atts['fields']['phone']) . ') AGAINST (%s) AS score', $terms); } $from[] = CN_ENTRY_PHONE_TABLE; /* * If there are long word terms, perform a FULLTEXT query. */ if (!empty($terms)) { $where[] = $wpdb->prepare('MATCH (' . implode(', ', $atts['fields']['phone']) . ') AGAINST (%s IN BOOLEAN MODE)', $terms); } /* * If there are no long words and there are short words, perform a LIKE query for the short words. */ if (empty($terms) && !empty($shortwords)) { foreach ($shortwords as $word) { $like[] = $wpdb->prepare(implode(' LIKE %s OR ', $atts['fields']['phone']) . ' LIKE %s ', array_fill(0, count($atts['fields']['phone']), $wpdb->esc_like($word) . '%')); } $where[] = '( ' . implode(') OR (', $like) . ')'; } /* * Return the query results ordered by the relevance score. */ $orderBy = empty($terms) ? '' : ' ORDER BY score'; $sql = implode(', ', $select) . ' FROM ' . implode(',', $from) . ' WHERE ' . implode(' AND ', $where) . $orderBy; $ids = $wpdb->get_results($sql, ARRAY_A); /* * If any results are returned merge them in to the $scored results. */ if (!empty($ids)) { $scored = array_merge($scored, $ids); } } $scored = apply_filters('cn_search_scored_results', $scored, $terms); /* * The query results are stored in the $scored array ordered by relevance. * Only the entry ID/s are needed to be returned. Setup the $results array * with only the entry ID/s in the same order as returned by the relevance score. */ foreach ($scored as $entry) { $results[] = isset($entry['id']) ? $entry['id'] : $entry['entry_id']; } } /* * If no results are found, perhaps to the way MySQL performs FULLTEXT queries, FULLTEXT search being disabled * or the DB not supporting FULLTEXT, run a LIKE query. * * Perform the search on each table individually because joining the tables doesn't scale when * there are a large number of entries. */ if ((cnSettingsAPI::get('connections', 'search', 'keyword_enabled') && empty($results) || cnSettingsAPI::get('connections', 'search', 'fulltext_enabled') && empty($results)) && !empty($atts['terms'])) { /* * Only search the primary records if at least one fields is selected to be searched. */ if (!empty($atts['fields']['entry'])) { $like = array(); // Reset the like array. foreach ($atts['terms'] as $term) { /* * Attempt to secure the query using $wpdb->prepare() and like_escape() * * Since $wpdb->prepare() required var for each directive in the query string we'll use array_fill * where the count based on the number of columns that will be searched. */ $like[] = $wpdb->prepare(implode(' LIKE %s OR ', $atts['fields']['entry']) . ' LIKE %s ', array_fill(0, count($atts['fields']['entry']), '%' . $wpdb->esc_like($term) . '%')); } $sql = 'SELECT ' . CN_ENTRY_TABLE . '.id FROM ' . CN_ENTRY_TABLE . ' WHERE (' . implode(') OR (', $like) . ')'; //print_r($sql); $results = array_merge($results, $wpdb->get_col($sql)); //print_r($results);die; } /* * Only search the address records if at least one fields is selected to be searched. */ if (!empty($atts['fields']['address'])) { $like = array(); // Reset the like array. foreach ($atts['terms'] as $term) { /* * Attempt to secure the query using $wpdb->prepare() and like_escape() * * Since $wpdb->prepare() required var for each directive in the query string we'll use array_fill * where the count based on the number of columns that will be searched. */ $like[] = $wpdb->prepare(implode(' LIKE %s OR ', $atts['fields']['address']) . ' LIKE %s ', array_fill(0, count($atts['fields']['address']), '%' . $wpdb->esc_like($term) . '%')); } $sql = 'SELECT ' . CN_ENTRY_ADDRESS_TABLE . '.entry_id FROM ' . CN_ENTRY_ADDRESS_TABLE . ' WHERE (' . implode(') OR (', $like) . ')'; //print_r($sql); $results = array_merge($results, $wpdb->get_col($sql)); //print_r($results); } /* * Only search the phone records if the field is selected to be search. */ if (!empty($atts['fields']['phone'])) { $like = array(); // Reset the like array. foreach ($atts['terms'] as $term) { /* * Attempt to secure the query using $wpdb->prepare() and like_escape() * * Since $wpdb->prepare() required var for each directive in the query string we'll use array_fill * where the count based on the number of columns that will be searched. */ $like[] = $wpdb->prepare(implode(' LIKE %s OR ', $atts['fields']['phone']) . ' LIKE %s ', array_fill(0, count($atts['fields']['phone']), '%' . $wpdb->esc_like($term) . '%')); } $sql = 'SELECT ' . CN_ENTRY_PHONE_TABLE . '.entry_id FROM ' . CN_ENTRY_PHONE_TABLE . ' WHERE (' . implode(') OR (', $like) . ')'; //print_r($sql); $results = array_merge($results, $wpdb->get_col($sql)); //print_r($results); } } return apply_filters('cn_search_results', $results, $atts); }
/** * Add the the current Connections category description or entry bio excerpt as the page meta description. * * @access private * @since 0.7.8 * @static * * @uses get_query_var() * @uses esc_attr() * @uses strip_shortcodes() * * @return string */ public static function metaDesc() { global $connections; // Whether or not to filter the page title with the current directory location. if (!cnSettingsAPI::get('connections', 'connections_seo_meta', 'page_desc')) { return; } if (get_query_var('cn-cat-slug')) { // If the category slug is a descendant, use the last slug from the URL for the query. $categorySlug = explode('/', get_query_var('cn-cat-slug')); if (isset($categorySlug[count($categorySlug) - 1])) { $categorySlug = $categorySlug[count($categorySlug) - 1]; } $term = $connections->term->getTermBy('slug', $categorySlug, 'category'); $category = new cnCategory($term); $description = $category->getExcerpt(array('length' => 160)); } if (get_query_var('cn-cat')) { if (is_array(get_query_var('cn-cat'))) { return; } $categoryID = get_query_var('cn-cat'); $term = $connections->term->getTermBy('id', $categoryID, 'category'); $category = new cnCategory($term); $description = $category->getExcerpt(array('length' => 160)); } if (get_query_var('cn-entry-slug')) { $result = $connections->retrieve->entries(array('slug' => urldecode(get_query_var('cn-entry-slug')))); $entry = new cnEntry($result[0]); $description = $entry->getExcerpt(array('length' => 160)); } if (empty($description)) { return; } echo '<meta name="description" content="' . esc_attr(trim(strip_shortcodes(strip_tags(stripslashes($description))))) . '"/>' . "\n"; }
public static function card($entry, $template, $atts) { ?> <div class="cn-entry" style="-moz-border-radius:4px; background-color:#FFFFFF; border:1px solid #E3E3E3; color: #000000; margin:8px 0px; padding:6px; position: relative;"> <div style="width:49%; float:<?php echo is_rtl() ? 'right' : 'left'; ?> "> <?php $entry->getImage(); ?> <div style="clear:both;"></div> <div style="margin-bottom: 10px;"> <div style="font-size:larger;font-variant: small-caps"><strong><?php echo $entry->getNameBlock(); ?> </strong></div> <?php $entry->getTitleBlock(); ?> <?php $entry->getOrgUnitBlock(); ?> <?php $entry->getContactNameBlock(); ?> </div> <?php $entry->getAddressBlock(); ?> </div> <div align="right"> <?php $entry->getFamilyMemberBlock(); ?> <?php $entry->getPhoneNumberBlock(); ?> <?php $entry->getEmailAddressBlock(); ?> <?php $entry->getSocialMediaBlock(); ?> <?php $entry->getImBlock(); ?> <?php $entry->getLinkBlock(); ?> <?php $entry->getDateBlock(); ?> </div> <div style="clear:both"></div> <?php echo $entry->getBioBlock(); ?> <div style="clear:both"></div> <div class="cn-meta" align="left" style="margin-top: 6px"> <?php $entry->getContentBlock($atts['content'], $atts, $template); ?> <div style="display: block; margin-bottom: 8px;"><?php $entry->getCategoryBlock(array('separator' => ', ', 'before' => '<span>', 'after' => '</span>')); ?> </div> <?php if (cnSettingsAPI::get('connections', 'connections_display_entry_actions', 'vcard')) { $entry->vcard(array('before' => '<span>', 'after' => '</span>')); } ?> <?php cnTemplatePart::updated(array('timestamp' => $entry->getUnixTimeStamp(), 'style' => array('font-size' => 'x-small', 'font-variant' => 'small-caps', 'position' => 'absolute', 'right' => '36px', 'bottom' => '8px'))); cnTemplatePart::returnToTop(array('style' => array('position' => 'absolute', 'right' => '8px', 'bottom' => '5px'))); ?> </div> </div> <?php }
/** * Add the the current Connections category description or entry bio excerpt as the page meta description. * * @access private * @since 0.7.8 * @static * * @uses cnQuery::getVar() * @uses esc_attr() * @uses strip_shortcodes() */ public static function metaDesc() { // Whether or not to filter the page title with the current directory location. if (!cnSettingsAPI::get('connections', 'seo_meta', 'page_desc')) { return; } $description = ''; if (cnQuery::getVar('cn-cat-slug')) { // If the category slug is a descendant, use the last slug from the URL for the query. $categorySlug = explode('/', cnQuery::getVar('cn-cat-slug')); if (isset($categorySlug[count($categorySlug) - 1])) { $categorySlug = $categorySlug[count($categorySlug) - 1]; } $term = cnTerm::getBy('slug', $categorySlug, 'category'); $category = new cnCategory($term); $description = $category->getExcerpt(array('length' => 160)); } if (cnQuery::getVar('cn-cat')) { if (is_array(cnQuery::getVar('cn-cat'))) { return; } $categoryID = cnQuery::getVar('cn-cat'); $term = cnTerm::getBy('id', $categoryID, 'category'); $category = new cnCategory($term); $description = $category->getExcerpt(array('length' => 160)); } if (cnQuery::getVar('cn-entry-slug')) { // Grab an instance of the Connections object. $instance = Connections_Directory(); $result = $instance->retrieve->entries(array('slug' => urldecode(cnQuery::getVar('cn-entry-slug')))); // Make sure an entry is returned and then echo the meta desc. if (!empty($result)) { $entry = new cnEntry($result[0]); $description = $entry->getExcerpt(array('length' => 160)); } } if (0 == strlen($description)) { return; } echo '<meta name="description" content="' . esc_attr(trim(strip_shortcodes(strip_tags(stripslashes($description))))) . '"/>' . "\n"; }
/** * The private recursive function to build the category link item. * * Accepted option for the $atts property are: * type (string) * show_empty (bool) Whether or not to display empty categories. * show_count (bool) Whether or not to display the category count. * * @param object $category A category object. * @param int $level The current category level. * @param int $depth The depth limit. * @param array $slug An array of the category slugs to be used to build the permalink. * @param array $atts * @return string */ private static function categoryLinkDescendant($category, $level, $depth, $slug, $atts) { /** * @var WP_Rewrite $wp_rewrite * @var connectionsLoad $connections */ global $wp_rewrite; $out = ''; $defaults = array('show_empty' => TRUE, 'show_count' => TRUE, 'exclude' => array(), 'force_home' => FALSE, 'home_id' => cnSettingsAPI::get('connections', 'connections_home_page', 'page_id')); $atts = wp_parse_args($atts, $defaults); // Do not show the excluded category as options. if (!empty($atts['exclude']) && in_array($category->term_id, $atts['exclude'])) { return $out; } if ($atts['show_empty'] || !empty($category->count) || !empty($category->children)) { $count = $atts['show_count'] ? ' (' . $category->count . ')' : ''; /* * Determine of pretty permalink is enabled. * If it is, add the category slug to the array which will be imploded to be used to build the URL. * If it is not, set the $slug to the category term ID. */ if ($wp_rewrite->using_permalinks()) { $slug[] = $category->slug; } else { $slug = array($category->slug); } /* * Get tge current category from the URL / query string. */ if (cnQuery::getVar('cn-cat-slug')) { // Category slug $queryCategorySlug = cnQuery::getVar('cn-cat-slug'); if (!empty($queryCategorySlug)) { // If the category slug is a descendant, use the last slug from the URL for the query. $queryCategorySlug = explode('/', $queryCategorySlug); if (isset($queryCategorySlug[count($queryCategorySlug) - 1])) { $currentCategory = $queryCategorySlug[count($queryCategorySlug) - 1]; } } } elseif (cnQuery::getVar('cn-cat')) { $currentCategory = cnQuery::getVar('cn-cat'); } else { $currentCategory = ''; } $out .= '<li class="cat-item cat-item-' . $category->term_id . ($currentCategory == $category->slug || $currentCategory == $category->term_id ? ' current-cat' : '') . ' cn-cat-parent">'; // Create the permalink anchor. $out .= cnURL::permalink(array('type' => 'category', 'slug' => implode('/', $slug), 'title' => $category->name, 'text' => $category->name . $count, 'home_id' => $atts['home_id'], 'force_home' => $atts['force_home'], 'return' => TRUE)); /* * Only show the descendants based on the following criteria: * - There are descendant categories. * - The descendant depth is < than the current $level * * When descendant depth is set to 0, show all descendants. * When descendant depth is set to < $level, call the recursive function. */ if (!empty($category->children) && ($depth <= 0 ? -1 : $level) < $depth) { $out .= '<ul class="children cn-cat-children">'; foreach ($category->children as $child) { $out .= self::categoryLinkDescendant($child, $level + 1, $depth, $slug, $atts); } $out .= '</ul>'; } $out .= '</li>'; } return $out; }
/** * Process a logo upload, creating its size variation and caching it for later use. * * NOTE: The entry slug should be run thru rawurldecode() before being passed to this method. * * @access private * @since 8.1 * @static * @uses Connections_Directory() * @uses is_wp_error() * @uses cnMessage::set() * @uses cnImage::get() * @uses is_admin() * @param string $entrySlug The entry slug. * * @return array An associative array containing the the details about the uploaded logo. */ private static function processLogo($entrySlug) { if (!isset($_FILES['original_logo'])) { return FALSE; } // Grab an instance of the Connections object. $instance = Connections_Directory(); if (is_wp_error($img = cnImage::upload($_FILES['original_logo'], $entrySlug))) { cnMessage::set('error', implode('<br />', $img->get_error_messages())); return FALSE; } $cropMode = array(0 => 'none', 1 => 'crop', 2 => 'fill', 3 => 'fit'); $logo = cnImage::get($img['url'], array('crop_mode' => ($key = array_search(cnSettingsAPI::get('connections', 'image_logo', 'ratio'), $cropMode)) || $key === 0 ? $key : 2, 'width' => cnSettingsAPI::get('connections', 'image_logo', 'width'), 'height' => cnSettingsAPI::get('connections', 'image_logo', 'height'), 'quality' => cnSettingsAPI::get('connections', 'image_logo', 'quality'), 'sub_dir' => $entrySlug), 'data'); if (is_wp_error($logo)) { cnMessage::set('error', implode('<br />', $logo->get_error_messages())); } // Output the debug log. if ($instance->options->getDebug() && is_admin()) { if (isset($logo['log'])) { cnMessage::runtime('notice', 'Logo Image Process Log<br/> <pre>' . $logo['log'] . '</pre>'); } } return $img; }
/** * Run the actions registered to custom content blocks. * * Render any custom content blocks registered to the `cn_entry_output_content-{id}` action hook. * * This will also run any actions registered for a custom metaboxes and its fields. * The actions should hook into `cn_output_meta_field-{key}` to be rendered. * * Accepted option for the $atts property are: * id (string) The custom block ID to render. * order (mixed) array | string An indexed array of custom content block IDs that should be rendered in the order in the array. * If a string is provided, it should be a comma delimited string containing the content block IDs. It will be converted to an array. * exclude (array) An indexed array of custom content block IDs that should be excluded from being rendered. * include (array) An indexed array of custom content block IDs that should be rendered. * NOTE: Custom content block IDs in `exclude` outweigh custom content block IDs in include. Meaning if the * same custom content block ID exists in both, the custom content block will be excluded. * * @access public * @since 0.8 * @uses do_action() * @uses wp_parse_args() * @uses apply_filters() * @uses has_action() * @param mixed $atts array | string [optional] The custom content block(s) to render. * @param array $shortcode_atts [optional] If this is used within the shortcode template loop, the shortcode atts * should be passed so the shortcode atts can be passed by do_action() to allow access to the action callback. * @param cnTemplate|null $template [optional] If this is used within the shortcode template loop, the template object * should be passed so the template object can be passed by do_action() to allow access to the action callback. * * @return string The HTML output of the custom content blocks. */ public function getContentBlock($atts = array(), $shortcode_atts = array(), $template = NULL) { $blockContainerContent = ''; if (get_query_var('cn-entry-slug')) { $settings = cnSettingsAPI::get('connections', 'connections_display_single', 'content_block'); } else { $settings = cnSettingsAPI::get('connections', 'connections_display_list', 'content_block'); } $order = isset($settings['order']) ? $settings['order'] : array(); $include = isset($settings['active']) ? $settings['active'] : array(); $exclude = empty($include) ? $order : array(); $titles = array(); $defaults = array('id' => '', 'order' => is_string($atts) && !empty($atts) ? $atts : $order, 'exclude' => is_string($atts) && !empty($atts) ? '' : $exclude, 'include' => is_string($atts) && !empty($atts) ? '' : $include, 'layout' => 'list', 'container_tag' => 'div', 'block_tag' => 'div', 'header_tag' => 'h3', 'before' => '', 'after' => '', 'return' => FALSE); $atts = wp_parse_args(apply_filters('cn_output_content_block_atts', $atts), $defaults); if (!empty($atts['id'])) { $blocks = array($atts['id']); } elseif (!empty($atts['order'])) { // If `order` was supplied as a comma delimited string, convert it to an array. if (is_string($atts['order'])) { $blocks = stripos($atts['order'], ',') !== FALSE ? explode(',', $atts['order']) : array($atts['order']); } else { $blocks = $atts['order']; } } // Nothing to render, exit. if (empty($blocks)) { return ''; } // Cleanup user input. Trim whitespace and convert to lowercase. $blocks = array_map('strtolower', array_map('trim', $blocks)); // Output the registered action in the order supplied by the user. foreach ($blocks as $key) { isset($blockNumber) ? $blockNumber++ : ($blockNumber = 1); // Exclude/Include the metaboxes that have been requested to exclude/include. if (!empty($atts['exclude'])) { if (in_array($key, $atts['exclude'])) { continue; } } else { if (!empty($atts['include'])) { if (!in_array($key, $atts['include'])) { continue; } } } ob_start(); // If the hook has a registered meta data output callback registered, lets run it. if (has_action('cn_output_meta_field-' . $key)) { // Grab the meta. $results = $this->getMeta(array('key' => $key, 'single' => TRUE)); if (!empty($results)) { do_action("cn_output_meta_field-{$key}", $key, $results, $this, $shortcode_atts, $template); } } // Render the "Custom Fields" meta block content. if ('meta' == $key) { $this->getMetaBlock(array(), $shortcode_atts, $template); } $hook = "cn_entry_output_content-{$key}"; if (has_action($hook)) { do_action($hook, $this, $shortcode_atts, $template); } $blockContent = ob_get_clean(); if (empty($blockContent)) { continue; } $blockID = $this->getSlug() . '-' . $blockNumber; // Store the title in an array that can be accessed/passed from outside the content block loop. // And if there is no title for some reason, create one from the key. if ($name = cnOptions::getContentBlocks($key)) { $titles[$blockID] = $name; } elseif ($name = cnOptions::getContentBlocks($key, 'single')) { $titles[$blockID] = $name; } else { $titles[$blockID] = ucwords(str_replace(array('-', '_'), ' ', $key)); } //$titles[ $blockID ] = cnOptions::getContentBlocks( $key ) ? cnOptions::getContentBlocks( $key ) : ucwords( str_replace( array( '-', '_' ), ' ', $key ) ); $blockContainerContent .= apply_filters('cn_entry_output_content_block', sprintf('<%2$s class="cn-entry-content-block cn-entry-content-block-%3$s" id="cn-entry-content-block-%4$s">%1$s%5$s</%2$s>' . PHP_EOL, sprintf('<%1$s>%2$s</%1$s>', $atts['header_tag'], $titles[$blockID]), $atts['block_tag'], $key, $blockID, $blockContent), $this, $key, $blockID, $titles[$blockID], $blockContent, $atts, $shortcode_atts); } if (empty($blockContainerContent)) { return ''; } $out = apply_filters('cn_entry_output_content_block_container', sprintf('<%1$s class="cn-entry-content-block-%2$s">%3$s</%1$s>' . PHP_EOL, $atts['container_tag'], $atts['layout'], $blockContainerContent), $this, $blockContainerContent, $titles, $atts, $shortcode_atts); $out = $atts['before'] . $out . $atts['after'] . PHP_EOL; return $this->echoOrReturn($atts['return'], $out); }
/** * Geocode the supplied address. * * @access public * @since 0.7.3 * @version .5 * @todo Add support for the bounds, language and regions params * @todo support Open Street Map * @uses wp_parse_args() * @uses wp_remote_get() * @uses wp_remote_retrieve_body() * @param object $address * @param array $atts [optional] * @return object */ public static function address($address, $atts = array()) { $result = new stdClass(); $query = array(); $googleAddrURL = 'https://maps.googleapis.com/maps/api/geocode/%s?address=%s'; $defaults = array('provider' => 'google', 'output' => 'json'); $key = cnSettingsAPI::get('connections', 'google_maps_geocoding_api', 'server_key'); if (0 < strlen($key)) { $googleAddrURL = $googleAddrURL . '&key=' . urlencode($key); } $atts = wp_parse_args($atts, $defaults); if (is_array($address)) { $address = (object) $address; } switch ($atts['provider']) { case 'google': if (!empty($address->line_1)) { $query[] = trim($address->line_1); } if (!empty($address->line_2)) { $query[] = trim($address->line_2); } if (!empty($address->line_3)) { $query[] = trim($address->line_3); } if (!empty($address->city)) { $query[] = trim($address->city); } if (!empty($address->state)) { $query[] = trim($address->state); } if (!empty($address->zipcode)) { $query[] = trim($address->zipcode); } if (!empty($address->country)) { $query[] = trim($address->country); } // Convert the array to a string for the URL $query = implode(',', $query); // Remove non alpha numeric chars such as extra spaces and replace w/ a plus. //$query = preg_replace("[^A-Za-z0-9]", '+', $query ); //$query = urlencode( utf8_encode( str_replace( ' ', '+', $query ) ) ); $query = urlencode($query); $query = sprintf($googleAddrURL, $atts['output'], $query); $request = wp_remote_get($query); $body = wp_remote_retrieve_body($request); if ($body) { $json = json_decode($body); if (is_object($json) && 'OK' === $json->status) { // Rewrite the response from the Google API to be a bit more user friendly even though the nomenclature may not be the most accurate. // Address types from the API are documented here: https://developers.google.com/maps/documentation/geocoding/#Types // The formatted address. $result->formatted = $json->results[0]->formatted_address; // Setup the rest of the properties. $result->street_number = ''; $result->route = ''; $result->locality = ''; $result->region = ''; $result->region_abbr = ''; $result->county = ''; $result->township = ''; $result->postal_code = ''; $result->country = ''; $result->country_abbr = ''; foreach ($json->results[0]->address_components as $component) { if (isset($component->types)) { // Street Number if (in_array('street_number', $component->types)) { $result->street_number = $component->long_name; } // Road if (in_array('route', $component->types)) { $result->route = $component->long_name; } // City if (in_array('locality', $component->types)) { $result->locality = $component->long_name; } // State || Province or similar based on country political boundaries. if (in_array('administrative_area_level_1', $component->types)) { $result->region = $component->long_name; } if (in_array('administrative_area_level_1', $component->types)) { $result->region_abbr = $component->short_name; } // County or similar based on country political boundaries. if (in_array('administrative_area_level_2', $component->types)) { $result->county = $component->long_name; } // Township or similar based on country political boundaries. if (in_array('administrative_area_level_3', $component->types)) { $result->township = $component->long_name; } // Postal Code if (in_array('postal_code', $component->types)) { $result->postal_code = $component->long_name; } // Country if (in_array('country', $component->types)) { $result->country = $component->long_name; } if (in_array('country', $component->types)) { $result->country_abbr = $component->short_name; } } } $result->latitude = $json->results[0]->geometry->location->lat; $result->longitude = $json->results[0]->geometry->location->lng; //var_dump($json); //var_dump($result);die; } } break; case 'osm': break; } return $result; }
/** * 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; }
public static function card($entry, $template, $atts) { ?> <div class="cn-entry" style="-moz-border-radius:4px; background-color:#FFFFFF; border:1px solid #E3E3E3; color: #000000; margin:8px 0px; padding:6px; position: relative;"> <table width="100%" border="0px" bgcolor="#FFFFFF" bordercolor="#E3E3E3" cellspacing="0px" cellpadding="0px" style="margin: 0; vertical-align: top;"> <tr> <td align="left" width="50%" valign="top" style="vertical-align: top;"> <?php echo $entry->getImage(); ?> <div style="clear:both; margin: 0 5px;"> <div style="margin-bottom: 10px;"> <div style="font-size:larger;font-variant: small-caps"><strong><?php echo $entry->getNameBlock(); ?> </strong></div> <?php $entry->getTitleBlock(); ?> <?php $entry->getOrgUnitBlock(); ?> <?php $entry->getContactNameBlock(); ?> </div> <?php $entry->getAddressBlock(); ?> </div> </td> <td align="right" valign="top" style="vertical-align: top;"> <div style="clear:both; margin: 5px 5px;"> <?php $entry->getConnectionGroupBlock(); ?> <?php $entry->getPhoneNumberBlock(); ?> <?php $entry->getEmailAddressBlock(); ?> <?php $entry->getImBlock(); ?> <?php $entry->getSocialMediaBlock(); ?> <?php $entry->getLinkBlock(); ?> <?php $entry->getDateBlock(); ?> </div> </td> </tr> <tr> <td colspan="2"> <?php $entry->getContentBlock($atts['content'], $atts, $template); ?> <div style="display: block; margin-bottom: 8px;"><?php $entry->getCategoryBlock(array('separator' => ', ', 'before' => '<span>', 'after' => '</span>')); ?> </div> </td> </tr> <tr> <td valign="bottom" style="vertical-align: top;"> <?php if (cnSettingsAPI::get('connections', 'connections_display_entry_actions', 'vcard')) { $entry->vcard(array('before' => '<span>', 'after' => '</span>')); } ?> </td> <td align="right" valign="bottom" style="vertical-align: top;"> <?php cnTemplatePart::updated(array('timestamp' => $entry->getUnixTimeStamp(), 'style' => array('font-size' => 'x-small', 'font-variant' => 'small-caps', 'position' => 'absolute', 'right' => '36px', 'bottom' => '8px'))); cnTemplatePart::returnToTop(array('style' => array('position' => 'absolute', 'right' => '8px', 'bottom' => '5px'))); ?> </td> </tr> </table> </div> <?php }
/** * Return an array of image meta data. * * Accepted option for the $atts property are: * type (string) Valid options: logo | photo | custom. Default: photo * size (string) Valid options depend on `type`. * If `type` is `logo`: original | scaled. Default: original * If `type` is `photo`: original | thumbnail | medium | large. Default: original * If `type` is `custom`: Not used, use the `width` and `height` to set the custom size. * width (int) The width of the `custom` size. * height (int) The height of the `custom` size. * crop_mode (int) Which crop mode to utilize when rescaling the image. Valid range is 0–3. Default: 1 * 0 == Resize to Fit specified dimensions with no cropping. Aspect ratio will not be maintained. * 1 == Crop and resize to best fit dimensions maintaining aspect ration. Default. * 2 == Resize proportionally to fit entire image into specified dimensions, and add margins if required. * Use the canvas_color option to set the color to be used when adding margins. * 3 == Resize proportionally adjusting size of scaled image so there are no margins added. * quality (int) The image quality to be used when saving the image. Valid range is 1–100. Default: 80 * * The return array will contain the following keys and their value: * name => (string) The image name. * path => (string) The absolute image path. * url => (string) The image URL. * width => (int) The image width. * height => (int) The image height. * size => (string) The image size in a string, `height="yyy" width="xxx"`, that can be used directly in an img tag. * mime => (string) The image mime type. * type => (int) The IMAGETYPE_XXX constants indicating the type of the image. * * @access public * @since 8.1 * @uses apply_filters() * @uses wp_parse_args() * @uses self::getOriginalImageURL() * @uses self::getOriginalImagePath() * @uses cnImage::get() * @uses WP_Error * @uses is_wp_error() * @param array $atts * @return mixed array|WP_Error */ public function getImageMeta($atts = array()) { $cropMode = array(0 => 'none', 1 => 'crop', 2 => 'fill', 3 => 'fit'); $sizes = array('thumbnail', 'medium', 'large'); $meta = array(); $defaults = array('type' => 'photo', 'size' => 'original', 'width' => 0, 'height' => 0, 'crop_mode' => 1, 'quality' => 80); $defaults = apply_filters('cn_default_atts_image_meta', $defaults); $atts = wp_parse_args($atts, $defaults); if (empty($atts['type'])) { return $meta; } // The entry slug is saved in the db URL encoded, so it needs to be decoded. $slug = rawurldecode($this->getSlug()); if ('custom' == $atts['size']) { $meta = cnImage::get($this->getOriginalImageURL($atts['type']), array('crop_mode' => empty($atts['crop_mode']) && $atts['crop_mode'] !== 0 ? 1 : $atts['crop_mode'], 'width' => empty($atts['width']) ? NULL : $atts['width'], 'height' => empty($atts['height']) ? NULL : $atts['height'], 'quality' => $atts['quality'], 'sub_dir' => $slug), 'data'); if (!is_wp_error($meta)) { $meta['source'] = 'file'; } return $meta; } switch ($atts['type']) { case 'logo': switch ($atts['size']) { case 'original': $meta['path'] = $this->getOriginalImagePath($atts['type']); $meta['url'] = $this->getOriginalImageURL($atts['type']); if (isset($this->options['logo']['meta'])) { $meta = $this->options['logo']['meta']; // This needs to be here to ensure that the path and URL stored is updated // to the current path to account for users moving their site or changing // the site's folder structure. $meta['path'] = $this->getOriginalImagePath($atts['type']); $meta['url'] = $this->getOriginalImageURL($atts['type']); $meta['source'] = 'db'; } else { /** @noinspection PhpUsageOfSilenceOperatorInspection */ if (is_file($meta['path']) && ($image = @getimagesize($meta['path']))) { $meta['width'] = $image[0]; $meta['height'] = $image[1]; $meta['size'] = $image[3]; $meta['mime'] = $image['mime']; $meta['type'] = $image[2]; $meta['source'] = 'file'; } else { $meta = new WP_Error('image_not_found', __(sprintf('The file %s is not an image.', basename($meta['path'])), 'connections'), $meta['path']); } } break; default: $meta = cnImage::get($this->getOriginalImageURL($atts['type']), array('crop_mode' => ($key = array_search(cnSettingsAPI::get('connections', 'image_logo', 'ratio'), $cropMode)) || $key === 0 ? $key : 2, 'width' => cnSettingsAPI::get('connections', 'image_logo', 'width'), 'height' => cnSettingsAPI::get('connections', 'image_logo', 'height'), 'quality' => cnSettingsAPI::get('connections', 'image_logo', 'quality'), 'sub_dir' => $slug), 'data'); if (!is_wp_error($meta)) { $meta['source'] = 'file'; } break; } break; case 'photo': switch ($atts['size']) { case 'original': $meta['path'] = $this->getOriginalImagePath($atts['type']); $meta['url'] = $this->getOriginalImageURL($atts['type']); if (isset($this->options['image']['meta']['original'])) { $meta = $this->options['image']['meta']['original']; // This needs to be here to ensure that the path and URL stored is updated // to the current path to account for users moving their site or changing // the site's folder structure. $meta['path'] = $this->getOriginalImagePath($atts['type']); $meta['url'] = $this->getOriginalImageURL($atts['type']); $meta['source'] = 'db'; } else { /** @noinspection PhpUsageOfSilenceOperatorInspection */ if (is_file($meta['path']) && ($image = @getimagesize($meta['path']))) { $meta['width'] = $image[0]; $meta['height'] = $image[1]; $meta['size'] = $image[3]; $meta['mime'] = $image['mime']; $meta['type'] = $image[2]; $meta['source'] = 'file'; } else { $meta = new WP_Error('image_not_found', __(sprintf('The file %s is not an image.', basename($meta['path'])), 'connections'), $meta['path']); } } break; default: if (in_array($atts['size'], $sizes)) { $meta = cnImage::get($this->getOriginalImageURL($atts['type']), array('crop_mode' => ($key = array_search(cnSettingsAPI::get('connections', "image_{$atts['size']}", 'ratio'), $cropMode)) || $key === 0 ? $key : 2, 'width' => cnSettingsAPI::get('connections', "image_{$atts['size']}", 'width'), 'height' => cnSettingsAPI::get('connections', "image_{$atts['size']}", 'height'), 'quality' => cnSettingsAPI::get('connections', "image_{$atts['size']}", 'quality'), 'sub_dir' => $slug), 'data'); if (!is_wp_error($meta)) { $meta['source'] = 'file'; } } break; } break; } return $meta; }
/** * The dashboard widget used to display the upcoming anniversaries and birthdays. * * @access public * @since 0.8 * @param object $null Generally a $post or $entry object. Not used in Connections core. * @param array $metabox The metabox options array from self::register(). * @return string The recently added/modifed entries. */ public static function celebrate($null, $metabox) { $message = create_function('', 'return "' . $metabox['args']['message'] . '";'); add_filter('cn_upcoming_no_result_message', $message); $atts = array('list_type' => $metabox['args']['list_type'], 'days' => $metabox['args']['days'], 'include_today' => $metabox['args']['today'], 'private_override' => FALSE, 'date_format' => cnSettingsAPI::get('connections', 'connections_display_general', 'date_format'), 'show_lastname' => TRUE, 'list_title' => NULL, 'show_title' => FALSE, 'template' => 'dashboard-upcoming'); connectionsUpcomingList($atts); remove_filter('cn_upcoming_no_result_message', $message); }
/** * Creates the initial character filter control. * * Accepted option for the $atts property are: * return (bool) Whether or not to return or echo the result. * * @access public * @since 0.7.4 * @static * * @uses add_query_arg() * @uses get_query_var() * @uses wp_parse_args() * @uses is_admin() * * @param array $atts [description] * * @return string */ public static function index($atts = array()) { $links = array(PHP_EOL); $current = ''; $styles = ''; $defaults = array('status' => array('approved'), 'tag' => 'div', 'style' => array(), 'return' => FALSE); $atts = wp_parse_args($atts, $defaults); $characters = cnRetrieve::getCharacters($atts); // $currentPageURL = add_query_arg( array( 'page' => FALSE , 'cn-action' => 'cn_filter' ) ); // If in the admin init an instance of the cnFormObjects class to be used to create the URL nonce. if (is_admin()) { $form = new cnFormObjects(); } // Current character if (is_admin()) { if (isset($_GET['cn-char']) && 0 < strlen($_GET['cn-char'])) { $current = urldecode($_GET['cn-char']); } } else { if (get_query_var('cn-char')) { $current = urldecode(get_query_var('cn-char')); } } if (is_array($atts['style']) && !empty($atts['style'])) { array_walk($atts['style'], create_function('&$i, $property', '$i = "$property: $i";')); $styles = implode($atts['style'], '; '); } foreach ($characters as $key => $char) { $char = strtoupper($char); // If we're in the admin, add the nonce to the URL to be verified when settings the current user filter. if (is_admin()) { $links[] = '<a' . ($current == $char ? ' class="cn-char-current"' : ' class="cn-char"') . ' href="' . esc_url($form->tokenURL(add_query_arg(array('cn-char' => urlencode($char))), 'filter')) . '">' . $char . '</a> ' . PHP_EOL; } else { $url = cnURL::permalink(array('type' => 'character', 'slug' => $char, 'title' => $char, 'class' => $current == $char ? 'cn-char-current' : 'cn-char', 'text' => $char, 'home_id' => in_the_loop() && is_page() ? get_the_id() : cnSettingsAPI::get('connections', 'connections_home_page', 'page_id'), 'force_home' => FALSE, 'return' => TRUE)); $links[] = $url . PHP_EOL; } } $out = '<' . $atts['tag'] . ' class="cn-alphaindex"' . ($styles ? ' style="' . $styles . '"' : '') . '>' . implode(' ', $links) . '</' . $atts['tag'] . '>' . PHP_EOL; return self::echoOrReturn($atts['return'], $out); }
/** * Enqueue the template CSS file. * * @access private * @since 0.8 * @uses apply_filters() * @uses wp_enqueue_style() * * @return void */ public function enqueueCSS() { // Ensure the core CSS is added as a required CSS file when enqueueing the template's CSS. $required = cnSettingsAPI::get('connections', 'compatibility', 'css') ? array('cn-public') : array(); $required = apply_filters('cn_template_required_css-' . $this->slug, $required, $this); $handle = "cnt-{$this->slug}"; $url = cnURL::makeProtocolRelative($this->parts['css-url']); wp_enqueue_style($handle, $url, $required, $this->version); if (isset($this->parts['css-custom-url'])) { $customURL = cnURL::makeProtocolRelative($this->parts['css-custom-url']); wp_enqueue_style("cnt-{$this->slug}-custom", $customURL, array("cnt-{$this->slug}"), $this->version); } /** * Runs after the template's CSS and custom CSS have been enqueued. * * The variable part of the hook name is the template's slug. * * @since 8.4 * * @param string $handle The template's registered CSS handle. * @param array $required The template's registered dependencies. */ do_action('cn_template_enqueue_css-' . $this->slug, $handle, $required); }
/** * Whether or not login is required to view the directory or not. * * @access public * @since 8.2.5 * @static * * @uses cnSettingsAPI::get() * * @return bool */ public static function loginRequired() { return cnSettingsAPI::get('connections', 'login', 'required') ? TRUE : FALSE; }
/** * @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); }
/** * Render an unordered list of categories. * * This is the Connections equivalent of @see wp_list_categories() in WordPress core ../wp-includes/category-template.php * * @access public * @since 8.1.6 * @static * * @uses wp_parse_args() * @uses cnTerm::getTaxonomyTerms() * @uses cnURL::permalink() * @uses Walker::walk() * * @param array $atts { * Optional. An array of arguments. * NOTE: Additionally, all valid options as supported in @see cnTerm::getTaxonomyTerms(). * * @type string $show_option_all A non-blank value causes the display of a link to the directory home page. * Default: ''. The default is not to display a link. * Accepts: Any valid string. * @type string $show_option_none Set the text to show when no categories are listed. * Default: 'No Categories' * Accepts: Any valid string. * @type bool $show_count Whether or not to display the category count. * Default: FALSE * @type int $depth Controls how many levels in the hierarchy of categories are to be included in the list. * Default: 0 * Accepts: 0 - All categories and child categories. * -1 - All Categories displayed flat, not showing the parent/child relationships. * 1 - Show only top level/root parent categories. * n - Value of n (int) specifies the depth (or level) to descend in displaying the categories. * @type string $taxonomy The taxonomy tree to display. * Default: 'category' * Accepts: Any registered taxonomy. * @type bool $return Whether or not to return or echo the resulting HTML. * Default: FALSE * } * * @return string */ public static function render($atts = array()) { $out = ''; $defaults = array('show_option_all' => '', 'show_option_none' => __('No categories', 'connections'), 'orderby' => 'name', 'order' => 'ASC', 'show_count' => FALSE, 'hide_empty' => FALSE, 'child_of' => 0, 'exclude' => array(), 'hierarchical' => TRUE, 'depth' => 0, 'parent_id' => array(), 'taxonomy' => 'category', 'force_home' => FALSE, 'home_id' => cnSettingsAPI::get('connections', 'connections_home_page', 'page_id'), 'return' => FALSE); $atts = wp_parse_args($atts, $defaults); $atts['parent_id'] = wp_parse_id_list($atts['parent_id']); $walker = new self(); if (empty($atts['parent_id'])) { $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('name' => ''))); } else { $terms = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('include' => $atts['parent_id'], 'child_of' => 0, 'name' => ''))); // If any of the `parent_id` is not a root parent (where $term->parent = 0) set it parent ID to `0` // so the term tree will be properly constructed. foreach ($terms as $term) { if (0 !== $term->parent) { $term->parent = 0; } } foreach ($atts['parent_id'] as $termID) { $children = cnTerm::getTaxonomyTerms($atts['taxonomy'], array_merge($atts, array('child_of' => $termID, 'name' => ''))); if (!is_wp_error($children)) { $terms = array_merge($terms, $children); } } } /** * Allows extensions to add/remove class names to the term tree list. * * @since 8.5.18 * * @param array $class The array of class names. * @param array $terms The array of terms. * @param array $atts The method attributes. */ $class = apply_filters('cn_term_list_class', array('cn-cat-tree'), $terms, $atts); $class = cnSanitize::htmlClass($class); $out .= '<ul class="' . cnFunction::escAttributeDeep($class) . '">' . PHP_EOL; if (empty($terms)) { $out .= '<li class="cat-item-none">' . $atts['show_option_none'] . '</li>'; } else { if (cnQuery::getVar('cn-cat-slug')) { $slug = explode('/', cnQuery::getVar('cn-cat-slug')); // If the category slug is a descendant, use the last slug from the URL for the query. $atts['current_category'] = end($slug); } elseif ($catIDs = cnQuery::getVar('cn-cat')) { if (is_array($catIDs)) { // If value is a string, strip the white space and covert to an array. $catIDs = wp_parse_id_list($catIDs); // Use the first element $atts['current_category'] = reset($catIDs); } else { $atts['current_category'] = $catIDs; } } else { $atts['current_category'] = 0; } if (!empty($atts['show_option_all'])) { $out .= '<li class="cat-item-all"><a href="' . cnURL::permalink(array('type' => 'home', 'data' => 'url', 'return' => TRUE)) . '">' . $atts['show_option_all'] . '</a></li>'; } $out .= $walker->walk($terms, $atts['depth'], $atts); } $out .= '</ul>' . PHP_EOL; if ($atts['return']) { return $out; } echo $out; }
/** * Enqueues the Connections CSS on the frontend. * * @access private * @since 0.7.3.2 * @static * * @uses wp_enqueue_style() * @uses wp_style_is() * * @return void */ public static function enqueueStyles() { if (cnSettingsAPI::get('connections', 'compatibility', 'css')) { wp_enqueue_style('cn-public'); wp_enqueue_style('cn-chosen'); // If the custom CSS file was registered, lets enqueue it. if (wp_style_is('cn-public-custom', 'registered')) { wp_enqueue_style('cn-public-custom'); } } }
/** * Enqueue the template CSS file. * * @access private * @since 0.8 * @uses apply_filters() * @uses wp_enqueue_style() * * @return void */ public function enqueueCSS() { // Ensure the core CSS is added as a required CSS file when enqueueing the template's CSS. $required = cnSettingsAPI::get('connections', 'compatibility', 'css') ? array('cn-public') : array(); $required = apply_filters('cn_template_required_css-' . $this->slug, $required, $this); wp_enqueue_style("cnt-{$this->slug}", $this->parts['css-url'], $required, $this->version); if (isset($this->parts['css-custom-url'])) { wp_enqueue_style("cnt-{$this->slug}-custom", $this->parts['css-custom-url'], array("cnt-{$this->slug}"), $this->version); } }
/** * Remove end of line characters to support the themes that insist * on running wpautop() AFTER the shortcode filter has been run on * the_content. * * @access private * @since 0.8 * @static * @param string $string The result of executing any of the core Connections shortcodes. * * @return string The string with all EOL characters removed. */ public static function removeEOL($string) { if (cnSettingsAPI::get('connections', 'compatibility', 'strip_rnt')) { $search = array("\r\n", "\r", "\n", "\t", PHP_EOL); $replace = array(' '); $string = str_replace($search, $replace, $string); } return trim($string); }
/** * Generates a permalink for a taxonomy term. * * Filters: * cn_term_link * Passes: (string) $link, (object) $term, (string) $taxonomy * Return: $link * * NOTE: This is the Connections equivalent of get_term_link() in WordPress core ../wp-includes/taxonomy.php * * @access public * @since 8.1.6 * @static * * @uses cnTerm::get() * @uses cnTerm::getBy() * @uses is_wp_error() * @uses cnTerm::getAncestors() * @uses cnURL::permalink() * @uses apply_filters() * * @param object|int|string $term * @param string $taxonomy (optional if $term is object) * @param array $atts * * @return string|WP_Error URL to taxonomy term on success, WP_Error if term does not exist. */ public static function permalink($term, $taxonomy = '', $atts = array()) { /** @var $wp_rewrite WP_Rewrite */ //global $wp_rewrite; $defaults = array('force_home' => FALSE, 'home_id' => cnSettingsAPI::get('connections', 'connections_home_page', 'page_id')); $atts = cnSanitize::args($atts, $defaults); if (!is_object($term)) { if (is_int($term)) { $term = self::get($term, $taxonomy); } else { $term = self::getBy('slug', $term, $taxonomy); } } if (!is_object($term)) { $term = new WP_Error('invalid_term', __('Empty Term', 'connections')); } if (is_wp_error($term)) { return $term; } $taxonomy = $term->taxonomy; //$link = $wp_rewrite->get_extra_permastruct( $taxonomy ); //$slug = $term->slug; //$t = get_taxonomy( $taxonomy ); //if ( empty( $link ) ) { //if ( 'category' == $taxonomy ) { //$link = '?cat=' . $term->term_id; //} elseif ( $t->query_var ) { // // $term_link = "?$t->query_var=$slug"; //} else { // $link = "?taxonomy=$taxonomy&term=$slug"; //} //$link = home_url( $link ); //} else { //if ( $t->rewrite['hierarchical'] ) { $slugs = array(); $ancestors = self::getAncestors($term->term_id, $taxonomy); foreach ((array) $ancestors as $ancestor) { $ancestor_term = self::get($ancestor, $taxonomy); $slugs[] = $ancestor_term->slug; } $slugs = array_reverse($slugs); $slugs[] = $term->slug; $link = cnURL::permalink(array('type' => 'category', 'slug' => implode('/', $slugs), 'title' => $term->name, 'text' => $term->name, 'data' => 'url', 'force_home' => $atts['force_home'], 'home_id' => $atts['home_id'], 'return' => TRUE)); //} else { // // $term_link = str_replace( "%$taxonomy%", $slug, $term_link ); //} //$link = home_url( user_trailingslashit( $link, 'category' ) ); //} /** * Filter the term link. * * @since 8.1.6 * * @param string $link Term link URL. * @param object $term Term object. * @param string $taxonomy Taxonomy slug. */ return apply_filters('cn_term_link', $link, $term, $taxonomy); }