Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 429 Vote(s) - 3.53 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Custom post type yearly/ monthly archive

#1
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?
Reply

#2
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

[To see links please register here]

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 href="' . $a['link'] . '">' . $a['month'] . ' ' . $a['year'] . '</a></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] =>

[To see links please register here]

)

[1] => Array
(
[month] => January
[year] => 2013
[link] =>

[To see links please register here]

)

)

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.
Reply

#3
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');
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through