If you ever needed to create a blog fro your client running Drupal, you can’t help to wish certain aspects of WordPress would be part of Drupal. Undeniably one of those items is archive. Now granted WordPress has many widget extensions to make the archive look many different ways, the problem is, in Drupal there is no basic to base it on…

Archive Block
So recently i had a client who wanted to have an accordion archive tree for their website. they were using Drupal 7 and the previous developer after struggling with it for a while just gave up…
My first inclination was to just write it into the theme, but them mentioning that they plan to swap themes for different seasons, made this not sustainable solution. So i decided to create a custom PHP block, that way we could reuse it in any theme.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
<?php drupal_add_library('system', 'ui.accordion'); drupal_add_js('jQuery(document).ready(function(){jQuery("#archivetree").accordion({ active: "h3:last" });});', 'inline'); $result = db_query("SELECT DATE_FORMAT((DATE_ADD('19700101', INTERVAL node.created SECOND) + INTERVAL -18000 SECOND), '%Y%m') AS created_year_month, COUNT(node.nid) AS num_records FROM {node} node WHERE (( (node.status = '1') AND (node.type IN ('blog')) )) GROUP BY created_year_month ORDER BY created_year_month ASC"); foreach ($result as $record) { $created_year_month = $record->created_year_month; $num_records = $record->num_records; $year = substr($created_year_month, 0, 4); $month = substr($created_year_month, -2, 2); $month_name = date( 'F', mktime(0, 0, 0, $month) ); $archive_tree[$year][$month] = array( 'month' => $month, 'name' => $month_name, 'num_records' => $num_records, 'year' => $year, ); } $i_year = 0; foreach ($archive_tree as $list_year) { if ($i_year == 0){ $output = "<div id='archivetree'>\n"; $i_year++; } $i_month = 0; foreach ($list_year as $list_month) { if ($i_month == 0){ $output .= "<h3><a href='#'>"; $output .= $list_month['year']; $output .= "</a></h3>\n"; $output .= "<ul>\n"; $i_month++; } $text = $list_month['name']; $text .= " ("; $text .= $list_month['num_records']; $text .= ")"; $path = "blog/archive/"; $path .= $list_month['year']; $path .= "/"; $path .= $list_month['month']; $link = l($text,$path); $output .= "<li>$link</li>\n"; } $output .= "</ul>\n"; } $output .= "</div>\n"; print $output; ?> |
As you could see from the code we are using the ui.accordion from the jQuery UI which since Drupal 7 release is being included in the core.
Then my curiosity coupled with the fact that i had few more similar projects lined up won me over. I wanted to see if i could make it into Drupal module.
And “surprise” i have created the module learning few things along the way and breaking some drupal rules along the way… So here is how i have done it:
Step 1: create .info file, here is mine: (archive_accordion.info)
1 2 3 4 5 6 |
name = Archive Accordion description = Archive Accordion will give you a new block for the blog content type. package = User interface core = 7.x dependencies[] = block dependencies[] = views |
Step 2: Now that info file is created lets create the module file:(archive_accordion.module)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
<?php /** * @file * Archive Accordion will give you a new block for the blog content type. */ /** * Implements hook_help. * * Displays help and module information. * * @param path * Which path of the site we're using to display help * @param arg * Array that holds the current path as returned from arg() function */ function archive_accordion_help($path, $arg) { switch ($path) { case "admin/help#archive_accordion": return '<p>'. t("Archive Accordion will give you a new block for the blog content type") .'</p>'; break; } } /** * Implements hook_block_info(). */ function archive_accordion_block_info() { $blocks['archive_accordion'] = array( 'info' => t('Archive Accordion'), //The name that will appear in the block list. 'cache' => DRUPAL_CACHE_PER_ROLE, //Default ); return $blocks; } /** * Custom content function. * * @return * A result set of the targeted posts. */ function archive_accordion_contents(){ //Later fix Use Database API to retrieve current posts. /* $query = db_select('node', 'n') ->fields('n', array('nid', 'title', 'created')) ->condition('status', 1) //Published. ->condition('created', array($start_time, $end_time), 'BETWEEN') ->orderBy('created', 'DESC') //Most recent first. ->execute(); return $query; */ $result = db_query("SELECT DATE_FORMAT((DATE_ADD('19700101', INTERVAL node.created SECOND) + INTERVAL -18000 SECOND), '%Y%m') AS created_year_month, COUNT(node.nid) AS num_records FROM {node} node WHERE (( (node.status = '1') AND (node.type IN ('blog')) )) GROUP BY created_year_month ORDER BY created_year_month DESC"); return $result; } /** * Implements hook_block_view(). * * Prepares the contents of the block. */ function archive_accordion_block_view($delta = '') { switch($delta){ case 'archive_accordion': $block['subject'] = t('Archive Accordion'); if(user_access('access content')){ //Use our custom function to retrieve data. $result = archive_accordion_contents(); //Array to contain items for the block to render. $items = array(); //Iterate over the resultset and format as links. foreach ($result as $record) { $created_year_month = $record->created_year_month; $num_records = $record->num_records; $year = substr($created_year_month, 0, 4); $month = substr($created_year_month, -2, 2); $month_name = date( 'F', mktime(0, 0, 0, $month) ); $archive_tree[$year][$month] = array( 'month' => $month, 'name' => $month_name, 'num_records' => $num_records, 'year' => $year, ); } $i_year = 0; foreach ($archive_tree as $list_year) { if ($i_year == 0){ $output = "<div id='archivetree1'>\n"; $i_year++; } $i_month = 0; foreach ($list_year as $list_month) { if ($i_month == 0){ $output .= "<h3><a href='#'>"; $output .= $list_month['year']; $output .= "</a></h3>\n"; $output .= "<ul>\n"; $i_month++; } $text = $list_month['name']; $text .= " ("; $text .= $list_month['num_records']; $text .= ")"; $path = "blog/archive/"; $path .= $list_month['year']; $path .= "/"; $path .= $list_month['month']; $link = l($text,$path); $output .= "<li>$link</li>\n"; } $output .= "</ul>\n"; } $output .= "</div>\n"; if (empty($archive_tree)) { //No content. $block['content'] = t('No posts available.'); } else { //need to fix to Pass data through theme function. $block['content'] = $output; } } } $build['myelement']['#attached']['library'][] = array('system', 'ui.accordion'); $build['myelement']['#attached']['js'][] = array('data' => '(function($){$(function() { $("#archivetree1").accordion({ active: "h3:first" }); })})(jQuery);', 'type' => 'inline'); $output .= drupal_render($build); return $block; } /** * Implementation of hook_views_api(). */ function archive_accordion_views_api() { return array( 'api' => 3.0, ); } |
If you will look at the last part of the code above, you will notice that there is a reference to views api. the reason is that i also built a view that goes with it. (This was the easiest part, as all i had todo is export the view to code.) So here is the 3rd file in the folder (archive_accordion.views_default.inc)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
<?php /** * Implementation of hook_views_default_views(). */ function archive_accordion_views_default_views() { $view = new view; $view->name = 'blog_archive'; $view->description = 'This view works together with the Archive Accordion Block, if you didn't activate it yet please do... :) '; $view->tag = 'default'; $view->base_table = 'node'; $view->human_name = 'Blog Archive'; $view->core = 7; $view->api_version = '3.0'; $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ /* Display: Master */ $handler = $view->new_display('default', 'Master', 'default'); $handler->display->display_options['title'] = 'Blog Archive'; $handler->display->display_options['access']['type'] = 'perm'; $handler->display->display_options['cache']['type'] = 'none'; $handler->display->display_options['query']['type'] = 'views_query'; $handler->display->display_options['query']['options']['query_comment'] = FALSE; $handler->display->display_options['exposed_form']['type'] = 'basic'; $handler->display->display_options['pager']['type'] = 'full'; $handler->display->display_options['pager']['options']['items_per_page'] = '10'; $handler->display->display_options['style_plugin'] = 'default'; $handler->display->display_options['row_plugin'] = 'node'; $handler->display->display_options['row_options']['links'] = FALSE; /* Field: Content: Title */ $handler->display->display_options['fields']['title']['id'] = 'title'; $handler->display->display_options['fields']['title']['table'] = 'node'; $handler->display->display_options['fields']['title']['field'] = 'title'; $handler->display->display_options['fields']['title']['label'] = ''; $handler->display->display_options['fields']['title']['alter']['alter_text'] = 0; $handler->display->display_options['fields']['title']['alter']['make_link'] = 0; $handler->display->display_options['fields']['title']['alter']['absolute'] = 0; $handler->display->display_options['fields']['title']['alter']['word_boundary'] = 0; $handler->display->display_options['fields']['title']['alter']['ellipsis'] = 0; $handler->display->display_options['fields']['title']['alter']['strip_tags'] = 0; $handler->display->display_options['fields']['title']['alter']['trim'] = 0; $handler->display->display_options['fields']['title']['alter']['html'] = 0; $handler->display->display_options['fields']['title']['hide_empty'] = 0; $handler->display->display_options['fields']['title']['empty_zero'] = 0; $handler->display->display_options['fields']['title']['link_to_node'] = 1; /* Sort criterion: Content: Post date */ $handler->display->display_options['sorts']['created']['id'] = 'created'; $handler->display->display_options['sorts']['created']['table'] = 'node'; $handler->display->display_options['sorts']['created']['field'] = 'created'; $handler->display->display_options['sorts']['created']['order'] = 'DESC'; /* Contextual filter: Content: Created year */ $handler->display->display_options['arguments']['created_year']['id'] = 'created_year'; $handler->display->display_options['arguments']['created_year']['table'] = 'node'; $handler->display->display_options['arguments']['created_year']['field'] = 'created_year'; $handler->display->display_options['arguments']['created_year']['default_argument_type'] = 'fixed'; $handler->display->display_options['arguments']['created_year']['default_argument_skip_url'] = 0; $handler->display->display_options['arguments']['created_year']['summary']['number_of_records'] = '0'; $handler->display->display_options['arguments']['created_year']['summary']['format'] = 'default_summary'; $handler->display->display_options['arguments']['created_year']['summary_options']['items_per_page'] = '25'; /* Contextual filter: Content: Created month */ $handler->display->display_options['arguments']['created_month']['id'] = 'created_month'; $handler->display->display_options['arguments']['created_month']['table'] = 'node'; $handler->display->display_options['arguments']['created_month']['field'] = 'created_month'; $handler->display->display_options['arguments']['created_month']['default_argument_type'] = 'fixed'; $handler->display->display_options['arguments']['created_month']['default_argument_skip_url'] = 0; $handler->display->display_options['arguments']['created_month']['summary']['number_of_records'] = '0'; $handler->display->display_options['arguments']['created_month']['summary']['format'] = 'default_summary'; $handler->display->display_options['arguments']['created_month']['summary_options']['items_per_page'] = '25'; /* Filter criterion: Content: Published */ $handler->display->display_options['filters']['status']['id'] = 'status'; $handler->display->display_options['filters']['status']['table'] = 'node'; $handler->display->display_options['filters']['status']['field'] = 'status'; $handler->display->display_options['filters']['status']['value'] = 1; $handler->display->display_options['filters']['status']['group'] = 0; $handler->display->display_options['filters']['status']['expose']['operator'] = FALSE; /* Filter criterion: Content: Type */ $handler->display->display_options['filters']['type']['id'] = 'type'; $handler->display->display_options['filters']['type']['table'] = 'node'; $handler->display->display_options['filters']['type']['field'] = 'type'; $handler->display->display_options['filters']['type']['value'] = array( 'blog' => 'blog', ); /* Display: Page */ $handler = $view->new_display('page', 'Page', 'page'); $handler->display->display_options['path'] = 'blog/archive/%/%'; $views[$view->name] = $view; return $views; } |
Hope you enjoyed this brief tutorial, if you have any questions or suggestions please feel free to leave a comment.
3 Comments. Leave new
Thank You So much!! you are my saviour!
you are welcome!
Hi, im getting some errors like these.
Notice: Undefined variable: archive_tree in archive_accordion_block_view() (line 98 of C:wampnewwwwdrupalsitesallmodulesarchive_accordionarchive_accordion.module).
Warning: Invalid argument supplied for foreach() in archive_accordion_block_view() (line 98 of C:wampnewwwwdrupalsitesallmodulesarchive_accordionarchive_accordion.module).
Notice: Undefined variable: output in archive_accordion_block_view() (line 129 of C:wampnewwwwdrupalsitesallmodulesarchive_accordionarchive_accordion.module).
Please tell me how to correct it?…im not good with programming.