Last active
January 17, 2017 12:49
-
-
Save Bunkerbewohner/a12ba5c19f3bc1f339a18fa52efeb0cb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: List Posts with Custom Field | |
Plugin URI: http://www.christianschenk.org/projects/wordpress-list-posts-custom-field-plugin/ | |
Description: Inserts a list of posts with a certain custom field. | |
Version: 1.9.4 | |
Author: Christian Schenk | |
Author URI: http://www.christianschenk.org/ | |
*/ | |
# | |
# WordPress List Posts with Custom Field Plugin | |
# Copyright (C) 2007-2014 Christian Schenk | |
# | |
# This program is free software; you can redistribute it and/or | |
# modify it under the terms of the GNU General Public License | |
# as published by the Free Software Foundation; either version 2 | |
# of the License, or (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program; if not, write to the Free Software | |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA | |
# | |
# | |
# Constants | |
# | |
define('LPCF_PLACEHOLDER_PERMALINK', '%PERMALINK%'); | |
/** | |
* Finds posts that have a certain custom field attached and displays their | |
* title and excerpt in a HTML description list. | |
* | |
* Options: | |
* field: the custom field we're searching for | |
* orderby: colum of the posts table for "ORDER BY" | |
* order: ASC or DESC | |
* titlefield: uses another custom field for the title | |
* excerptfield: uses another custom field for the excerpt | |
* titleprefix, titlesuffix: string before or after the title | |
* excerptprefix, excerptsuffix: string before or after the excerpt | |
* category: posts have to belong to at least one of the given categories | |
* having: the posts/pages found need a field with the given value | |
* having_delim: delimiter for the having clause (delim for key / value) | |
* having_delim2: delimiter for the having clause (delim for multiple fields) | |
* having_conj: conjunction for the elements in the having clause (AND or OR) | |
* limit: lets you limit the number of results shown | |
* | |
* Note: field, titlefield and excerptfield may be a comma separated list. | |
*/ | |
function lpcf_shortcode($atts) { | |
global $wpdb; | |
extract(shortcode_atts(array('field' => '', | |
'orderby' => 'post_date', | |
'order' => 'DESC', | |
'titlefield' => '', | |
'excerptfield' => '', | |
'titleprefix' => '<a href="'.LPCF_PLACEHOLDER_PERMALINK.'">', | |
'titlesuffix' => '</a>', | |
'excerptprefix' => '', | |
'excerptsuffix' => '', | |
'display' => '', | |
'showlinks' => true, | |
'split' => false, | |
'category' => null, | |
'having' => '', | |
'having_delim' => ',', | |
'having_delim2' => '|', | |
'having_conj' => 'OR', | |
'daterange' => 'all', | |
'limit' => ''), $atts)); | |
# sanity checks | |
if (strlen(trim($field)) == 0) | |
return '<strong>'.__('No custom field found. Add it to the shortcode.', 'lpcf').'</strong>'; | |
if (strpos($field, ',') !== false) | |
$fields = explode(',', $field); | |
$order = strtolower($order); | |
if ($order != 'asc' and $order != 'desc') | |
return '<strong>'.__('Invalid order. Use "ASC" or "DESC".', 'lpcf').'</strong>'; | |
$titlefields = explode(',', $titlefield); | |
$excerptfields = explode(',', $excerptfield); | |
# extract categories | |
if ( !empty($category) ) { | |
$category = explode(',', $category); | |
$tmpCategory = array(); | |
foreach ($category as $cat) | |
if ( is_numeric($cat) ) | |
$tmpCategory[] = $cat; | |
$category = $tmpCategory; | |
} | |
# make sure that the user did not choose the having delimiters in a way | |
# that conflicts with the default values | |
if ($having_delim == $having_delim2) | |
return '<strong>'.__('Having delimiters must be different.', 'lpcf').'</strong>'; | |
# extract "having" custom fields and values | |
if (strpos($having, $having_delim) !== false) { | |
# split multiple key / value pairs | |
if (strpos($having, $having_delim2) !== false) | |
$having = explode($having_delim2, $having); | |
else | |
$having = array($having); # insert single key / value pair in array | |
# split all keys from their values | |
foreach ($having as $key => $value) { | |
if (strpos($value, $having_delim) === false) continue; | |
$having[$key] = explode($having_delim, $value); | |
} | |
} | |
# make sure that the having conjunction is either "and" or "or" | |
$having_conj = strtolower($having_conj); | |
if ($having_conj != 'and' and $having_conj != 'or') | |
return '<strong>'.__('Having conjunction must be either "and" or "or".', 'lpcf').'</strong>'; | |
# cater for multiple custom fields | |
$meta_key_sql = ''; | |
if ( isset($fields) ) { | |
for ($i = 0, $n = count($fields); $i < $n; $i++) { | |
$meta_key_sql .= 'm.meta_key = "'.$fields[$i].'"'; | |
if ($i != $n - 1) $meta_key_sql .= ' OR '; | |
} | |
} else { | |
$meta_key_sql = 'm.meta_key = "'.$field.'"'; | |
} | |
# orderby for SQL | |
$orderbysql = (strpos($orderby, 'cfvalue') === false) ? $orderby : 'post_date'; | |
# retrieve posts | |
$sql = 'SELECT DISTINCT p.ID, p.post_title AS title, p.post_excerpt AS excerpt, p.post_date AS date | |
FROM '.$wpdb->posts.' AS p, '.$wpdb->postmeta.' AS m | |
WHERE p.ID = m.post_id AND ('.$meta_key_sql.') AND p.post_status = "publish" | |
ORDER BY p.'.$orderbysql.' '.$order; | |
$result = $wpdb->get_results($sql); | |
if (empty($result)) return '<!--'.__('No posts found for these custom fields.', 'lpcf').'-->'; | |
# make sure that the posts belong to at least one of the given categories | |
if ( !empty($category) ) { | |
$tmpResult = array(); | |
for ($i = 0, $n = count($result); $i < $n; $i++) { | |
$post = $result[$i]; | |
foreach ($category as $cat) | |
if (lpcf_assert_category($post->ID, $cat) === true) { | |
$tmpResult[] = $post; | |
break; | |
} | |
} | |
$result = $tmpResult; | |
} | |
# split the posts according to their custom fields | |
if ($split == true and strpos($orderby, 'cfvalue') !== false) { | |
$tmpResult = array(); | |
lpcf_get_cfvalue($orderby, $result, false); | |
foreach ($result as $post) { | |
if (empty($post->cfvalue)) { | |
$tmpResult[] = $post; | |
continue; | |
} | |
foreach ($post->cfvalue as $curField) { | |
# PHP 4 compat, since "$tmpPost = clone $post" doesn't work. | |
$tmpPost =& new lpcf_post(); | |
$tmpPost->ID = $post->ID; | |
$tmpPost->title = $post->title; | |
$tmpPost->excerpt = $post->excerpt; | |
$tmpPost->date = $post->date; | |
$tmpPost->cfvalue = $curField; | |
$tmpResult[] = $tmpPost; | |
} | |
} | |
$result = $tmpResult; | |
} | |
# set correct title/excerpt | |
for ($i = 0, $n = count($result); $i < $n; $i++) { | |
$post = $result[$i]; | |
# set title to cfvalue, the given title fields or the default | |
if ( $split == true and !empty($post->cfvalue) ) | |
$title = $post->cfvalue; | |
else | |
$title = lpcf_get_custom_field($post->ID, $titlefields, $post->title); | |
# sort multiple custom fields alphabetically in ascending order by default | |
if (is_array($title)) | |
sort($title); | |
$result[$i]->title = lpcf_concat_array($title, $titleprefix, $titlesuffix); | |
if (strpos($result[$i]->title, LPCF_PLACEHOLDER_PERMALINK) !== false) | |
$result[$i]->title = str_replace(LPCF_PLACEHOLDER_PERMALINK, get_permalink($post->ID), $result[$i]->title); | |
$excerpt = lpcf_get_custom_field($post->ID, $excerptfields, $post->excerpt); | |
$result[$i]->excerpt = lpcf_concat_array($excerpt, $excerptprefix, $excerptsuffix); | |
} | |
# sort | |
if ($orderby == 'post_title') { | |
usort($result, 'lpcf_compare_title'); | |
} else if (strpos($orderby, 'cfvalue') !== false) { | |
# prepare cfvalue | |
if ($split == false) lpcf_get_cfvalue($orderby, $result); | |
foreach ($result as $post) | |
if ( is_array($post->cfvalue) ) | |
$post->cfvalue = empty($post->cfvalue[0]) == false ? $post->cfvalue[0] : ''; | |
usort($result, 'lpcf_compare_cfvalue'); | |
} | |
if ($order == 'desc') | |
$result = array_reverse($result); | |
# | |
# OUTPUT | |
# | |
$rVal .= "<dl>\n"; | |
for ($i = 0, $output_items = 0, $n = count($result); $i < $n; $i++) { | |
$post = $result[$i]; | |
# make sure that the post has the following fields set to the given value | |
if (!empty($having)) { | |
$having_skip = array(); | |
# compare the values of the keys with each other | |
foreach ($having as $having_pair) { | |
$having_pair_key = $having_pair[0]; | |
$having_pair_value = $having_pair[1]; | |
$havingFields = get_post_meta($post->ID, $having_pair_key, false); | |
# compare the values with each other | |
foreach ($havingFields as $havingField) | |
if ($havingField == $having_pair_value) | |
$having_skip[] = false; | |
} | |
# Evaluate the skip condition | |
if ( | |
# Empty array -> nothing matched | |
( empty($having_skip) ) OR | |
# Conjunction AND | |
# -> there must be as many "false" entries in the skip array as there are custom fields | |
( $having_conj == 'and' and count($having_skip) != count($having) ) OR | |
# Conjunction OR | |
# -> there must be at least one "false" entry in the skip array | |
( $having_conj == 'or' and !in_array(false, $having_skip) ) | |
) | |
continue; | |
} | |
# only display elements until the limit is reached | |
if (!empty($limit) and $output_items >= $limit) break; | |
# make sure the date is correct | |
# TODO | |
# get EM_Event instance for this event (see /classes/em-event.php) | |
$event = em_get_event($post->ID, "post_id"); | |
# get date using placeholder (see http://wp-events-plugin.com/documentation/placeholders/) | |
$date = $event->output("#_EVENTDATES") | |
# output | |
$rVal .= '<dt>'.$post->title."</dt>\n". | |
"<dd><time>$date</time><span>$post->excerpt</span></dd>\n"; | |
$output_items++; | |
} | |
$rVal .= "</dl>\n"; | |
return $rVal; | |
} | |
if (function_exists('add_shortcode')) { | |
add_shortcode('lp', 'lpcf_shortcode'); | |
add_shortcode('list-posts', 'lpcf_shortcode'); | |
} | |
/** | |
* PHP 4 compat | |
*/ | |
class lpcf_post { | |
var $ID; | |
var $title; | |
var $excerpt; | |
var $date; | |
var $cfvalue; | |
} | |
/** | |
* Fetches the value for the custom fields that should be used during the | |
* sorting algorithm. | |
*/ | |
function lpcf_get_cfvalue($orderby, &$result, $single = true) { | |
$cfkey = substr($orderby, strpos($orderby, ':') + 1, strlen($orderby)); | |
for ($i = 0, $n = count($result); $i < $n; $i++) { | |
$post = $result[$i]; | |
$result[$i]->cfvalue = get_post_meta($post->ID, $cfkey, $single); | |
} | |
} | |
/** | |
* Walks through all the given keys and checks whether the given post has a | |
* custom field with this particular key. If it does, the value gets returned, | |
* otherwise the default value will be used. | |
* | |
* Note that the order matters since we'll return the value of the first custom | |
* field that we find. | |
*/ | |
function lpcf_get_custom_field($postId, $keys, $default) { | |
if (empty($keys) or !is_array($keys)) return $default; | |
foreach ($keys as $key) { | |
if (empty($key)) continue; | |
$meta = get_post_meta($postId, $key, false); | |
if (!empty($meta)) return $meta; | |
} | |
return $default; | |
} | |
/** | |
* Compares the title field. | |
*/ | |
function lpcf_compare_title($a, $b) { | |
return strcmp($a->title, $b->title); | |
} | |
/** | |
* Compares the value of a custom field | |
*/ | |
function lpcf_compare_cfvalue($a, $b) { | |
return strcmp($a->cfvalue, $b->cfvalue) * -1; | |
} | |
/** | |
* Concatenates the elements of an array. | |
*/ | |
function lpcf_concat_array($array, $prefix, $suffix) { | |
if (!is_array($array)) | |
return $prefix . $array . $suffix; | |
$concat = ''; | |
foreach ($array as $elem) | |
$concat .= $prefix . $elem . $suffix; | |
return $concat; | |
} | |
/** | |
* Returns true if the given post belongs to the given category. | |
*/ | |
function lpcf_assert_category($postId, $categoryId) { | |
if ( !is_numeric($postId) or !is_numeric($categoryId) ) return true; | |
global $wpdb; | |
$sql = 'SELECT count(object_id) FROM '.$wpdb->term_relationships.' WHERE object_id = '.$postId.' AND term_taxonomy_id = '.$categoryId; | |
$result = $wpdb->get_var($sql); | |
if (empty($result)) | |
return false; | |
return true; | |
} | |
## FILE ENDS HERE ### |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment