Custom post type yearly/ monthly archive - sql

I have a custom post type "news" in my Wordpress site. I am using Advanced Custom Fields plugin to add meta data to each post.
I want to create an array of news items as an archive:
[2013]
[January] => 5
[2012]
[January] => 20
[February] => 10
[2011]
[April] => 30
I managed to get this working using:
global $wpdb;
$news = $wpdb->get_results(
"SELECT wp_posts.post_date, COUNT(wp_posts.ID) as count
FROM $wpdb->posts
WHERE
wp_posts.post_type = 'news' AND
wp_posts.post_status = 'publish' AND
wp_posts.post_date <= CURDATE() AND
wp_posts.post_date >= DATE_SUB(CURDATE(), INTERVAL 3 YEAR)
GROUP BY YEAR(wp_posts.post_date), MONTH(wp_posts.post_date)
ORDER BY wp_posts.post_date DESC",
ARRAY_A);
$archive = array();
foreach ($news as $post):
$year = date('Y', strtotime($post['post_date']));
$month = date('m', strtotime($post['post_date']));
$month_name = date('F', strtotime($post['post_date']));
$post['url'] = 'NOT SURE ABOUT URL';
$archive[$year][$month_name] = $post;
endforeach;
I need to be able to link to specific years and months using http://example.com/2012/ and http://example.com/2012/10/.
As this involves a custom post type "news" I'm unsure how to make this happen?

In order to do what you require, you need to modify Wordpress rewrites to be able to capture the year/month/etc post data for a custom post type.
You may do this with the following code:
/**
* Custom post type date archives
*/
/**
* Custom post type specific rewrite rules
* #return wp_rewrite Rewrite rules handled by Wordpress
*/
function cpt_rewrite_rules($wp_rewrite) {
$rules = cpt_generate_date_archives('news', $wp_rewrite);
$wp_rewrite->rules = $rules + $wp_rewrite->rules;
return $wp_rewrite;
}
add_action('generate_rewrite_rules', 'cpt_rewrite_rules');
/**
* Generate date archive rewrite rules for a given custom post type
* #param string $cpt slug of the custom post type
* #return rules returns a set of rewrite rules for Wordpress to handle
*/
function cpt_generate_date_archives($cpt, $wp_rewrite) {
$rules = array();
$post_type = get_post_type_object($cpt);
$slug_archive = $post_type->has_archive;
if ($slug_archive === false) return $rules;
if ($slug_archive === true) {
$slug_archive = $post_type->name;
}
$dates = array(
array(
'rule' => "([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})",
'vars' => array('year', 'monthnum', 'day')),
array(
'rule' => "([0-9]{4})/([0-9]{1,2})",
'vars' => array('year', 'monthnum')),
array(
'rule' => "([0-9]{4})",
'vars' => array('year'))
);
foreach ($dates as $data) {
$query = 'index.php?post_type='.$cpt;
$rule = $slug_archive.'/'.$data['rule'];
$i = 1;
foreach ($data['vars'] as $var) {
$query.= '&'.$var.'='.$wp_rewrite->preg_index($i);
$i++;
}
$rules[$rule."/?$"] = $query;
$rules[$rule."/feed/(feed|rdf|rss|rss2|atom)/?$"] = $query."&feed=".$wp_rewrite->preg_index($i);
$rules[$rule."/(feed|rdf|rss|rss2|atom)/?$"] = $query."&feed=".$wp_rewrite->preg_index($i);
$rules[$rule."/page/([0-9]{1,})/?$"] = $query."&paged=".$wp_rewrite->preg_index($i);
}
return $rules;
}
You will notice that I have hard-coded news in to the $rules = cpt_generate_date_archives('news', $wp_rewrite); portion of the code. You can change this as needed.
With this code, you should be able to navigate to http://yoursite.com/news/2013/02/ and receive an archive listing for that specific post type for that specific time.
For completeness, I will include how to generate a monthly archive widget in order to utilize this.
/**
* Get a montlhy archive list for a custom post type
* #param string $cpt Slug of the custom post type
* #param boolean $echo Whether to echo the output
* #return array Return the output as an array to be parsed on the template level
*/
function get_cpt_archives( $cpt, $echo = false )
{
global $wpdb;
$sql = $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE post_type = %s AND post_status = 'publish' GROUP BY YEAR($wpdb->posts.post_date), MONTH($wpdb->posts.post_date) ORDER BY $wpdb->posts.post_date DESC", $cpt);
$results = $wpdb->get_results($sql);
if ( $results )
{
$archive = array();
foreach ($results as $r)
{
$year = date('Y', strtotime( $r->post_date ) );
$month = date('F', strtotime( $r->post_date ) );
$month_num = date('m', strtotime( $r->post_date ) );
$link = get_bloginfo('siteurl') . '/' . $cpt . '/' . $year . '/' . $month_num;
$this_archive = array( 'month' => $month, 'year' => $year, 'link' => $link );
array_push( $archive, $this_archive );
}
if( !$echo )
return $archive;
foreach( $archive as $a )
{
echo '<li>' . $a['month'] . ' ' . $a['year'] . '</li>';
}
}
return false;
}
To use this function just supply the slug of the custom post type, ie: get_cpt_archives( 'news' ). This will return an array of unique Year/Dates/Links, ie:
Array
(
[0] => Array
(
[month] => February
[year] => 2013
[link] => http://yoursite.com/news/2013/02
)
[1] => Array
(
[month] => January
[year] => 2013
[link] => http://yoursite.com/news/2013/01
)
)
You can loop through these with a foreach and output them however you want.
Alternatively, you can use get_cpt_archives( 'news', true ) which will automatically echo each item wrapped in an <li> linking to its specific archive.
The formatting of the output is not exactly what you wanted, so you will have to tweak it a bit to get it to display in the
Year
Month
Month
Year
Month
format that you require.
I hope this helps.

I know this is an old post, but there is a much more succinct way of doing what the OP is asking:
function cpt_add_rewrite_rules()
{
$cpt = 'news';
add_rewrite_rule($cpt.'/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})?$',
'index.php?post_type='.$cpt.'&year=$matches[1]&monthnum=$matches[2]&day=$matches[3]',
'top');
add_rewrite_rule($cpt.'/([0-9]{4})/([0-9]{1,2})?$',
'index.php?post_type='.$cpt.'&year=$matches[1]&monthnum=$matches[2]',
'top');
add_rewrite_rule($cpt.'/([0-9]{4})?$',
'index.php?post_type='.$cpt.'&year=$matches[1]',
'top');
}
add_filter('init', 'cpt_add_rewrite_rules');

Related

Prestashop : Can't make my module work : Get order details when order status is changed to “shipped”

I am developing a module, it gets order details when order status is changed to "shipped" by admin, to post them to a third-party application with API.
I am using Prestashop V 1.7.7.0.
The hook i'm using is hookActionOrderStatusPostUpdate
The module is installed successfully in the Backoffice and there's no syntax errors, But it doesn't do anything.
Can't figure out what's wrong in my code.
Need help please. Thanks
<?php
/**
* 2007-2021 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license#prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* #author PrestaShop SA <contact#prestashop.com>
* #copyright 2007-2021 PrestaShop SA
* #license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
if (!defined('_PS_VERSION_')) {
exit;
}
class Cargo extends Module
{
protected $config_form = false;
public function __construct()
{
$this->name = 'cargo';
$this->tab = 'administration';
$this->version = '1.0.0';
$this->author = 'tekwave';
$this->need_instance = 1;
/**
* Set $this->bootstrap to true if your module is compliant with bootstrap (PrestaShop 1.6)
*/
$this->bootstrap = true;
parent::__construct();
$this->displayName = $this->l('cargo');
$this->description = $this->l('Ce module permet la synchronisation entre Prestashop et Cargo');
$this->confirmUninstall = $this->l('');
$this->ps_versions_compliancy = array('min' => '1.6', 'max' => _PS_VERSION_);
}
/**
* Don't forget to create update methods if needed:
* http://doc.prestashop.com/display/PS16/Enabling+the+Auto-Update
*/
public function install()
{
Configuration::updateValue('CARGO_LIVE_MODE', false);
return parent::install() &&
$this->registerHook('header') &&
$this->registerHook('backOfficeHeader') &&
$this->registerHook('actionOrderStatusPostUpdate');
}
public function uninstall()
{
Configuration::deleteByName('CARGO_LIVE_MODE');
return parent::uninstall();
}
/**
* Load the configuration form
*/
public function getContent()
{
/**
* If values have been submitted in the form, process.
*/
if (((bool)Tools::isSubmit('submitCargoModule')) == true) {
$this->postProcess();
}
$this->context->smarty->assign('module_dir', $this->_path);
$output = $this->context->smarty->fetch($this->local_path.'views/templates/admin/configure.tpl');
return $output.$this->renderForm();
}
/**
* Create the form that will be displayed in the configuration of your module.
*/
protected function renderForm()
{
$helper = new HelperForm();
$helper->show_toolbar = false;
$helper->table = $this->table;
$helper->module = $this;
$helper->default_form_language = $this->context->language->id;
$helper->allow_employee_form_lang = Configuration::get('PS_BO_ALLOW_EMPLOYEE_FORM_LANG', 0);
$helper->identifier = $this->identifier;
$helper->submit_action = 'submitCargoModule';
$helper->currentIndex = $this->context->link->getAdminLink('AdminModules', false)
.'&configure='.$this->name.'&tab_module='.$this->tab.'&module_name='.$this->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->tpl_vars = array(
'fields_value' => $this->getConfigFormValues(), /* Add values for your inputs */
'languages' => $this->context->controller->getLanguages(),
'id_language' => $this->context->language->id,
);
return $helper->generateForm(array($this->getConfigForm()));
}
/**
* Create the structure of your form.
*/
protected function getConfigForm()
{
return array(
'form' => array(
'legend' => array(
'title' => $this->l('Settings'),
'icon' => 'icon-cogs',
),
'input' => array(
array(
'type' => 'switch',
'label' => $this->l('Live mode'),
'name' => 'CARGO_LIVE_MODE',
'is_bool' => true,
'desc' => $this->l('Use this module in live mode'),
'values' => array(
array(
'id' => 'active_on',
'value' => true,
'label' => $this->l('Enabled')
),
array(
'id' => 'active_off',
'value' => false,
'label' => $this->l('Disabled')
)
),
),
array(
'col' => 3,
'type' => 'text',
'prefix' => '<i class="icon icon-envelope"></i>',
'desc' => $this->l('Enter a valid email address'),
'name' => 'CARGO_ACCOUNT_EMAIL',
'label' => $this->l('Email'),
),
array(
'type' => 'password',
'name' => 'CARGO_ACCOUNT_PASSWORD',
'label' => $this->l('Password'),
),
),
'submit' => array(
'title' => $this->l('Save'),
),
),
);
}
/**
* Set values for the inputs.
*/
protected function getConfigFormValues()
{
return array(
'CARGO_LIVE_MODE' => Configuration::get('CARGO_LIVE_MODE', true),
'CARGO_ACCOUNT_EMAIL' => Configuration::get('CARGO_ACCOUNT_EMAIL', 'contact#prestashop.com'),
'CARGO_ACCOUNT_PASSWORD' => Configuration::get('CARGO_ACCOUNT_PASSWORD', null),
);
}
/**
* Save form data.
*/
protected function postProcess()
{
$form_values = $this->getConfigFormValues();
foreach (array_keys($form_values) as $key) {
Configuration::updateValue($key, Tools::getValue($key));
}
}
/**
* Add the CSS & JavaScript files you want to be loaded in the BO.
*/
public function hookBackOfficeHeader()
{
if (Tools::getValue('module_name') == $this->name) {
$this->context->controller->addJS($this->_path.'views/js/back.js');
$this->context->controller->addCSS($this->_path.'views/css/back.css');
}
}
/**
* Add the CSS & JavaScript files you want to be added on the FO.
*/
public function hookHeader()
{
$this->context->controller->addJS($this->_path.'/views/js/front.js');
$this->context->controller->addCSS($this->_path.'/views/css/front.css');
}
This is my code under hookActionOrderStatusPostUpdate function :
public function hookActionOrderStatusPostUpdate($params)
{
if ($params['newOrderStatus']->id == 6) {
$order = new Order((int)$params['id_order']);
$address = new Address((int)$order->id_address_delivery);
$country = new Country((int)($address->id_country));
$state = new State((int)($address->id_state));
$message = new Message((int)($order->id_message));
$Products = $order->getProducts();
$tel_cl = $address->phone;
$nom_prenom_cl = $address->lastname . ' ' . $address->firstname;
$ville_cl = $country->name;
$delegation_cl = $state->name;
$adresse_cl = $address->address1 . ' ' . $address->address2;
$tel_2_cl = $address->phone_mobile;
$libelle = '';
$nb_piece = 0;
foreach ($Products as $product) {
$libelle .= $product['product_name'] . '<br/>';
$nb_piece += $product['product_quantity'];
}
$cod = $order->total_paid;
$remarque = $message->message;
$Url_str = 'http://admin.cargotunisie.com/cargo_api/set_colis_cargo_get.php?id=1&tel_cl='.$tel_cl.'&nom_prenom_cl='.$nom_prenom_cl.'&ville_cl='.$ville_cl.'&delegation_cl='.$delegation_cl.'&adresse_cl='.$adresse_cl.'&tel_2_cl='.$tel_2_cl.'&libelle='.$libelle.'&cod='.$cod.'&nb_piece='.$nb_piece.'&remarque='.$remarque;
$json = Tools::file_get_contents($Url_str);
$result = json_decode($json);
}
}
}
It could be due to several things.
First: make sure the hook is hooked.
Go to Design > Positions > Then add new hook
Choose your module's name and check if you can select the hook actionOrderStatusPostUpdate. If you can, then it means it was unhooked.
This happens more than we would like, and sometimes you can get crazy until you found it
If that doesn't work you can try this (only if is not on a production site). If it is, just wrap it by using an if that checks if it's from your IP.
Add Tools::dieObject($params); at the beginning of the function.
Then change the an order and check the results. You should see a user friendly list of the values stored in $params.
Make it sure the $params['newOrderStatus'] exists and $params['newOrderStatus']->id is an object.
Also, it should be pretty obvious, but make sure the order ID which are you doing the tests is 6.
With that you should be able to have a general clue of what may be happening.

How can I change the WordPress Custom Post & Categories to New Custom Post & Categories

In my database I have 2 custom post type and their category.
Old Post Type and Category
Post Type = real-estate
Category = re-category
Mew Post Type and Category
Post Type = real_estate
Category = real_estate_category
Now I want to convert all old post type and their categories to new custom post type and their categories.
So, using this code I can get all the old post type and can change the old post type to new post type BUT how can I change the old post type's attached categories to new post type categories?
add_action( 'template_redirect', 'everstrap_do_migration' );
function everstrap_do_migration() {
// Convert their real-estate to real_estate post type
if( $_REQUEST['action'] && $_REQUEST['action'] == 'convert_re_post_type' ) {
global $wpdb;
$old_custom_post_type = 'real-estate';
$ne_custom_post_type = 'real_estate';
// A sql query to return all real-esate post
$results = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_title FROM {$wpdb->posts} WHERE post_type = %s and post_status = 'publish'", $old_custom_post_type ), ARRAY_A );
// Return null if we found no results
if ( ! $results )
return;
foreach ( $result as $key => $value) {
// Update query
$update = $wpdb->update(
$wpdb->posts,
array(
'post_type' => $new_custom_post_type,
),
array(
'post_type' => $old_custom_post_type,
),
array(
'%s',
),
array(
'%s'
)
);
if( $update ) {
echo 'Updated post id ' . $value['ID'];
} else {
echo 'can\' update';
}
}
// echo '<pre>';
// print_r( $results );
// echo '</pre>';
}
}
$new = "real_estate_category";
$old = "re-category";
$cat = get_terms( array (
'taxonomy' => $old,
'hide_empty' => false,
));
global $wpdb;
$table = $wpdb->prefix . "term_taxonomy";
foreach ($cat as $c) {
$wpdb->update($table, array("taxonomy" => $new), array("term_id" => $c->term_id), array("%s"));
}

What is post type of Replies in Wordpress BBPress?

I did count active in 7 days topics of my Wordpress page. But It counts only Active (replied) topics not actual replies- I need more dynamic number to lure people using forum.
function count_new_forum_posts() {
$today = date("Y-m-d");
$date2 = date("Y-m-d", strtotime($today . "-7 Day"));
$args = array(
'post_type' => 'topic',
'meta_query' => array(
array(
'key' => '_bbp_last_active_time',
'value' => $date2,
'type' => 'DATE',
'compare' => '>='
),
)
);
$posts_query = new WP_Query($args);
$the_count = $posts_query->post_count;
return $the_count;
}
add_filter('wp_nav_menu_items', 'new_forums_notice_to_menu', 10, 2);
function new_forums_notice_to_menu($items, $args) {
if(count_new_forum_posts() > 0){
if( $args->theme_location == 'primary' )
$items .= '<li><font color="red">Šios savaitės naujos žinutės forume: <span>'.count_new_forum_posts().'</span></font></li>';
return $items;
}else{
if( $args->theme_location == 'primary' )
$items .= '<li><font color="gray">Šią savaitę forume dar niekas nepasisakė</span></font></li>';
return $items;
}
}
When i try to change post_type to 'reply' or 'replies' It counts to 0.

Trouble passing SQL data to view in codeigniter

I have a form that I am using to allow people to input data and then upload a preset picture. I want to label that picture as the form_id. I am able to run a LAST_INSERT_ID() query and display it after I insert the form in my view but I can't seem to echo that information out anywhere else. I need the query to select_last_id to run after my $update query or the ID number will be off. Could anyone assist in helping me pass just the value of the row to my view? Here is the code from my controller.
function inspection() {
if($this->input->post('submit')) {
$array = array(
'trlr_num' => $this->input->post('trlr_num'),
'seal' => $this->input->post('seal'),
'damaged' => $this->input->post('damaged'),
'truck_num' => $this->input->post('truck_num'),
'driver_name' => $this->input->post('driver_name'),
'car_code' => $this->input->post('car_code'),
'origin' => $this->input->post('origin'),
'lic_plate' => $this->input->post('lic_plate'),
'del_note' => $this->input->post('del_note'),
'live_drop' => $this->input->post('live_drop'),
'temp' => $this->input->post('temp'),
'level' => $this->input->post('level'),
'ship_num' => $this->input->post('ship_num'),
'trlr_stat' => $this->input->post('trlr_stat'),
'comment' => $this->input->post('comment')
);
$update = $this->trailer_model->insert_form($array);
$query = $this->trailer_model->select_last_id();
$result =& $query->result_array();
$this->table->set_heading('ID');
$data['table'] = $this->table->generate_table($result);
unset($query,$result);
}
$level = $this->trailer_model->select_fuel_level();
$result = $level->result_array();
$data['options'] = array();
foreach($result as $key => $row) {
$data['options'][$row['level']] = $row['level'];
}
unset($query,$result,$key,$row);
$data['label_display'] = 'Fuel Level';
$data['field_name'] = 'level';
$status = $this->trailer_model->select_trailer_type();
$result = $status->result_array();
$data['options1'] = array();
foreach($result as $key => $row) {
$data['options1'][$row['trlr_stat']] = $row['trlr_stat'];
}
unset($query,$result,$key,$row);
$data['label_display1'] = 'Trailer Status';
$data['field_name1'] = 'trlr_stat';
$data['page_title'] = 'Trailer Inspection';
$data['main_content'] = 'dlx/inspection/trailer_inspection_view';
return $this->load->view('includes/template',$data);
}
}
Anything you want to display on a view, you must pass to it.
When you're setting $data, you missed adding $query to it.
Controller:
I understand that $query = $this->trailer_model->select_last_id(); is returning just an ID, so:
$data['last_id'] = $query;
But if $query = $this->trailer_model->select_last_id(); does not return just an ID, but an array or something else, you shall include to return the ID in your model method. Actually, it'd be crucial to know what $this->trailer_model->select_last_id(); is returning.
View:
echo $last_id; -> must echo the last ID, if select_last_id() method from your model returns what it has to return.

Custom post type + taxonomy term yearly/monthly archive

-
I have been researching on how to create a date archive for a custom post which has a taxonomy and various terms...
I have had great success with this Stackoverflow answer from walltea however I need some help with modifying it to also take into account taxonomies and its terms...
Is this possible?
--EDIT--
Ok I managed to do this after LOADS of time on it, If you know if a better solution to this then please do share as the way I found is a little bit cumbersome: (again original code curtosy of walltea's Stackoverflow answer)
1.
In your functions.php place this code: (changing the custom posts types that you have for '$cptPart')
/**
* Custom post type date archives
*/
/**
* Custom post type specific rewrite rules
* #return wp_rewrite Rewrite rules handled by Wordpress
*/
add_action('generate_rewrite_rules', 'cpt_rewrite_rules');
/**
* Generate date archive rewrite rules for a given custom post type
* #param string $cpt slug of the custom post type
* #return rules returns a set of rewrite rules for Wordpress to handle
*/
function cpt_rewrite_rules($wp_rewrite) {
$rules = array();
$cptPart = "(news_events|live_reports|book_review|readers_digest|publications|jobs)";
$taxonomyPart = "([a-zA-Z_-]+)";
$termPart = "([a-zA-Z_-]+)";
$patterns = array(
array(
'rule' => "$cptPart/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/$taxonomyPart/$termPart",
'vars' => array('post_type', 'year', 'monthnum', 'day', 'taxonomy', 'term')
),
array(
'rule' => "$cptPart/([0-9]{4})/([0-9]{1,2})/$taxonomyPart/$termPart",
'vars' => array('post_type', 'year', 'monthnum', 'taxonomy', 'term')
),
array(
'rule' => "$cptPart/([0-9]{4})/$taxonomyPart/$termPart",
'vars' => array('post_type', 'year', 'taxonomy', 'term')
),
array(
'rule' => "$cptPart/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/$taxonomyPart",
'vars' => array('post_type', 'year', 'monthnum', 'day', 'taxonomy')
),
array(
'rule' => "$cptPart/([0-9]{4})/([0-9]{1,2})/$taxonomyPart",
'vars' => array('post_type', 'year', 'monthnum', 'taxonomy')
),
array(
'rule' => "$cptPart/([0-9]{4})/$taxonomyPart",
'vars' => array('post_type', 'year', 'taxonomy')
),
array(
'rule' => "$cptPart/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})",
'vars' => array('post_type', 'year', 'monthnum', 'day')
),
array(
'rule' => "$cptPart/([0-9]{4})/([0-9]{1,2})",
'vars' => array('post_type', 'year', 'monthnum')
),
array(
'rule' => "$cptPart/([0-9]{4})",
'vars' => array('post_type', 'year')
),
);
foreach ($patterns as $pattern) {
$i = 1;
$params = array();
foreach ($pattern['vars'] as $var) {
$params[] = $var . '=' . $wp_rewrite->preg_index($i);
$i++;
}
$query = 'index.php?' . implode('&', $params);
$rules[$pattern['rule']."/?$"] = $query;
$rules[$pattern['rule']."/feed/(feed|rdf|rss|rss2|atom)/?$"] = $query."&feed=".$wp_rewrite->preg_index($i);
$rules[$pattern['rule']."/(feed|rdf|rss|rss2|atom)/?$"] = $query."&feed=".$wp_rewrite->preg_index($i);
$rules[$pattern['rule']."/page/([0-9]{1,})/?$"] = $query."&paged=".$wp_rewrite->preg_index($i);
}
$wp_rewrite->rules = $rules + $wp_rewrite->rules;
return $wp_rewrite;
}
/**
* Get a montlhy archive list for a custom post type
* #param string $cpt Slug of the custom post type
* #param boolean $echo Whether to echo the output
* #return array Return the output as an array to be parsed on the template level
*/
function get_cpt_archives($cpt, $echo = false, $taxomony = null, $term = null)
{
global $wpdb;
$conditions = "";
if ($taxomony) {
$conditions .= " AND wtt.taxonomy LIKE %s";
if ($term) {
$conditions .= " AND wt.slug LIKE %s";
}
}
$sql = $wpdb->prepare("
SELECT *
FROM wp_posts p
LEFT JOIN wp_term_relationships wtr ON wtr.object_id = p.ID
LEFT JOIN wp_term_taxonomy wtt ON wtr.term_taxonomy_id = wtt.term_taxonomy_id
LEFT JOIN wp_terms wt ON wtt.term_id = wt.term_id
WHERE post_type = %s
AND post_status = 'publish'
$conditions
GROUP BY YEAR(p.post_date),
MONTH(p.post_date)
ORDER BY p.post_date DESC
", $cpt, $taxomony, $term);
$results = $wpdb->get_results($sql);
if ( $results )
{
$archive = array();
foreach ($results as $r)
{
$year = date('Y', strtotime( $r->post_date ) );
$month = date('F', strtotime( $r->post_date ) );
$month_num = date('m', strtotime( $r->post_date ) );
$link = get_bloginfo('siteurl') . '/' . $cpt . '/' . $year . '/' . $month_num;
if ($taxomony) {
$link .= "/" . $r->taxonomy;
if ($term) {
$link .= "/" . $r->slug;
}
}
$this_archive = array( 'month' => $month, 'year' => $year, 'link' => $link );
array_push( $archive, $this_archive );
}
if( !$echo )
return $archive;
foreach( $archive as $a )
{
echo '<li>' . $a['month'] . ' ' . $a['year'] . '</li>';
}
}
return false;
}
-
2. In your custom archive file (for example one of mine was archive-publications.php) place this code above the loop:
<?php
function lr_posts_join($join) {
global $taxonomy_global_join;
global $term_global_join;
if ($taxonomy_global_join) $join .= " $taxonomy_global_join";
if ($term_global_join) $join .= " $term_global_join";
return $join;
}
function lr_posts_where($where) {
global $taxonomy_global_where;
global $term_global_where;
if ($taxonomy_global_where) $where .= " $taxonomy_global_where";
if ($term_global_where) $where .= " $term_global_where";
return $where;
}
add_filter('posts_join', 'lr_posts_join');
add_filter('posts_where', 'lr_posts_where');
$extraArgs = "";
if (get_query_var('taxonomy')) {
$taxonomy_global_join = "
LEFT JOIN $wpdb->term_relationships wtr ON wtr.object_id = $wpdb->posts.ID
LEFT JOIN $wpdb->term_taxonomy wtt ON wtr.term_taxonomy_id = wtt.term_taxonomy_id ";
$taxonomy_global_where = " AND wtt.taxonomy LIKE '" . esc_sql(like_escape(get_query_var('taxonomy'))) . "'";
$extraArgs .= "&taxonomy=" . get_query_var('taxonomy');
if (get_query_var('term')) {
$term_global_join = "
LEFT JOIN $wpdb->terms wt ON wtt.term_id = wt.term_id ";
$term_global_where = " AND wt.slug LIKE '" . esc_sql(like_escape(get_query_var('term'))) . "'";
$extraArgs .= "&term=" . get_query_var('term');
}
}
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$posts = query_posts("post_type=publications&paged=$paged$extraArgs");
$taxonomy_global_join = $taxonomy_global_where = '';
$term_global_join = $term_global_where = '';
while (have_posts()) : the_post(); ?>
-- loop code here --
<?php endwhile; ?>
3. The above code lets our archive page understand our filtering for taxonomies and terms. Save your files and re-save your permalinks in the admin area. Next lets use this puppy! I used this in my custom sidebar (sidebar-publications.php):
<ul>
<?php echo get_cpt_archives( 'publications', true, 'publication_category', 'articles' ) ?>
</ul>
Our function gets the custom post (Publications) and 'true' is set so we want the normal list layout. Next it calls the taxonomy we want... I just have one for this custom post ( publication_category ) and finally the term I want in that taxonomy ( articles ). This should spit out a link like this: www.website/custom_post/year/month/taxonomy/term
I hope this code serves you well! My client is very happy ;)
Very Best,
Chris