The Date API creates date elements that can be used by any module, including 'date_select', 'date_textfield', and 'date_timezone'.

With this feature of the awesome Date API I had success using date API elements in a module I am working on. Now I am searching for a simple way to use these elements as Date arguments in Views. Looking at the function _date_api_fields() in date_api_fileds.inc it seems, that only CCK date fields and core timestamp fields (with hard coded names like 'created' or 'updated') get identified as date fields for the Date argument handler. Does anybody know a solution for integrating non CCK Date API elements as date arguments in the Date argument handler?

Comments

greg.harvey’s picture

*bump*

We're trying to work this out too! Any suggestions?

greg.harvey’s picture

Looks to us like a better solution is to create your own handler extending the views_handler_argument_date handler provided by the Views module. You can see examples in ./sites/all/modules/views/modules/node/views_handler_argument_dates_various.inc ... the Date module probably should allow people to pass in their own date fields to be supplied as arguments in the date argument handler, but it doesn't seem to, in spite of this misleading release note:

- Add a flexible date argument to the API that will work on any Views date field and take any ISO date argument.

http://drupal.org/node/269300
It seems the above just means there is a flexible means of passing date arguments to some pre-determined date fields.

However, simply copying the Views module's own views_handler_argument_node_created_week did it for us. =)

KarenS’s picture

The key requirement for any datefield that can be used in this way is that it has to be available as a Views field because there is a lot of field information Views will need to use -- like what the field name is and what table it is stored in and what options for formatting the output should be made available. So you would first have to use the Views API to inform Views about your fields and tables.

Once your field is available as a views field I can use it in date arguments and filters. I scan through all the available Views fields to see which are date fields and that's the point where I need to add a way that you can tell me your field should be used. That piece is still missing but should be quite simple to add.

Unfortunately, there is no simple way for you to just say 'use my field', the Date and Calendar APIs rely heavily on all the field info that Views uses.

greg.harvey’s picture

Thanks Karen - we were just reviewing this now - it seems to us (and correct me if I'm wrong) that the date_api_fields() function (which in turn calls the private _date_api_fields() function) builds the checkbox list of available date fields for the Date API argument handler. So what we would like to see (and I guess this is a feature request?) is some way of registering a field as belonging to the date API so that function includes it.

Is that something that exists and we've missed, or is this a new feature request?

Edit:

That piece is still missing but should be quite simple to add.

YES PLEASE!!!! =)

KarenS’s picture

Yes, I'll add a way to register it, but that still won't work unless you have used the Views API to make your fields available to Views. I'll add that piece soon, but it won't do you any good unless you make your fields into Views fields. That's the part that is hard, and I can't do it for you.

KarenS’s picture

In case I'm not being clear, your fields must be fields that show up on the 'Fields' list in Views as fields you can add to any view. If they aren't there is nothing the Date argument can do. The Date argument is intended to

work on any Views date field

.

Maybe I'm misunderstanding you, but it doesn't look to me like you've gotten that part done. If you have and you're waiting for me to take it from there, I'll add something in, but I have other things to do right now and I'm not going to work on this unless you've gotten to that point.

greg.harvey’s picture

Hi Karen - understood - we've already done that bit! It's actually not that hard really... it's just a hook, after all. =)

I think the Date module handles grouping of rows with the same interface does it not?

For reference, this is our hook code - I guess, once your changes are made we won't need the argument handler at all because our field will show up in your Date argument:

/**
 * Define extra filters for the views module.
 */
function content_distribution_views_data(){
  $data = array();
	
  // Define the base group of this table. Fields that don't
  // have a group defined will go into this field by default.
  $data['content_distribution']['table']['group']  = t('Content Distribution');

  $data['content_distribution']['table']['base'] = array(
    'field' => 'nid',
    'title' => t('Content Distribution'),
    'help' => t("Content distribution relates to nodes which are set up to be distributed remotely."),
  );
  
  $data['content_distribution']['table']['join'] = array(
    'node' => array(
      'left_field' => 'nid',
      'field' => 'nid',
    ),
  );	
  // ----------------------------------------------------------------
  // Fields
  
  //published date
  $data['content_distribution']['published_date'] = array(
    'title' => t('Published Date'),
    'help' => t('Date and time of when node is set to be published.'),
    'field' => array(
      'handler' => 'views_handler_field_date',
      'click sortable' => TRUE,
    ),
    'sort' => array(
      'handler' => 'views_handler_sort_date',
    ),
    'filter' => array(
      'handler' => 'views_handler_filter_date',
    ),
  );
  
  //week argument
  $data['content_distribution']['published_week'] = array(
    'title' => t('Published week'),
    'help' => t('In the form of WW (01 - 53).'),
    'argument' => array(
      'field' => 'published_date',
      'handler' => 'views_handler_argument_node_created_week',
    ),
  );
  return $data;
}
KarenS’s picture

OK, you did know what you were doing :) Sorry!

This will be easy, I can test for any fields that use the 'views_handler_field_date' handler. Just give me a few minutes to work something up and commit it and you can try it out.

KarenS’s picture

Oops, not quite that easy. I need a way to know what kind of date you've created so I can create the right SQL. All the core dates are timestamps that store the value as UTC and use the site/user timezone, so I know how to set them up. With custom fields I'll need to know the type of date and how it handles timezones.

greg.harvey’s picture

Hmmm, well for D6 you could look at hook_schema() ...? Not sure how that would work, but the info is there...

KarenS’s picture

Status: Active » Needs review

That won't tell me what your timezone handling is. Anyway, I've worked something up and I'm getting ready to commit it. You would have to provide a hook that looks like this, and then clear the Views cache to get the fields list to re-generate:


function content_distribution_date_api_fields($field) {
  if ($field == 'content_distribution.published_date') {
    return array(
      'sql_type' => DATE_ISO, // or DATE_UNIX or DATE_DATETIME
      'tz_handling' => 'site', // or 'none' or 'date' or 'utc'
   );
}

I don't have time to try to test this, so I'll let you test it :)

greg.harvey’s picture

Awesome! So if we download the latest dev snapshot and apply that hook, things will hopefully work? Will test tomorrow (I'm in the UK) and let you know. =)

Thank you so much!

KarenS’s picture

Status: Needs review » Fixed

No report back, but the hook was added to the code, hook_date_api_fields(), to allow other modules to define date fields that can use the date argument and date filter.

greg.harvey’s picture

Oh, sorry - I don't remember what happened with this. Will try to remember to feed back when I return to work.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

darrick’s picture

I've tested the new hook and it works as expected. Thanks.

allartk’s picture

= fixed =

allartk’s picture

Another question, what if I want those fields as a start and end date field in calendar? Any idea?

allartk’s picture

for everyone else finding this the answer:

function yacalendar_date_api_fields($field) {
  if ($field == 'yacalendar_node.startdate') {
    return array(
      'sql_type' => DATE_UNIX, // or DATE_UNIX or DATE_DATETIME
      'tz_handling' => 'site', // or 'none' or 'date' or 'utc'
      'fromto' => array('yacalendar_node_startdate','yacalendar_node_enddate'),
      'related_fields' => array('yacalendar_node_startdate','yacalendar_node_enddate'),
   ); }
  if ($field == 'yacalendar_node.enddate') {
    return array(
      'sql_type' => DATE_UNIX, // or DATE_UNIX or DATE_DATETIME
      'tz_handling' => 'site', // or 'none' or 'date' or 'utc'
   ); } 
   
}
gollyg’s picture

Version: 6.x-2.x-dev » 6.x-2.4
Status: Closed (fixed) » Active

I am trying to implement the above hooks in a custom module. More specifically the hooks:

  • date_api_fields
  • date_api_tables

However they never seem to fire. I have tried clearing caches, disabling and enabling modules, but nothing seems to trigger them (I am testing through a debugger with breakpoints and also a simple dsm through the devel module).

A search through the date code does not seem to reveal any invoke functions calling these hooks, although they may well be there.

Can anyone confirm that theses hooks are implemented as per the advanced help section in 6.x-2.4? Are there any extra steps to register a module with the date module?

gollyg’s picture

I should clarify - the hook_date_api_fields does not seem to fire, the hook_date_api_tables does fire.

gollyg’s picture

Status: Active » Closed (fixed)

Okay, ignore that last question - I see the modules are invoked from the views_handler. Still not firing in my implementation, but I will look into it a bit more before bothering you again ;)

zilverdistel’s picture

I couldn't get this to work either, until I added a 'base' element in my hook_views_data() array for the corresponding date field(s):


    'date_start' => array(
      'title' => t('Start date'),
      'help' => t('Displays the start date of a subscription.'),
      'field' => array(
        // this handler extends views_handler_field_date
        'handler' => 'views_handler_field_datetime',
        'click sortable' => TRUE,
      ),
      'sort' => array(
        'handler' => 'views_handler_sort_date',
      ),
      'filter' => array(
        'handler' => 'date_api_filter_handler',
        // No idea why exactly I had to add this 'base' element, but I got a 'Missing date fields!' message when configuring the filter
        // When debugging date_api_fields, I noticed the missing '$base' argument, I expected it to be 'gft_subscription', but it was                    
        // empty.
        // 'node' is the default argument there, so only default fields where tested and  wewweb_gftform_date_api_fields() never got 
        // fired.
        // I tried adding the following line on severel positions in this array, Everything worked when I put it in the 'filter' element.
      	'base' => 'gft_subscription',
      ),
    ),
bbeeson’s picture

I had the same problem of trying to use Calandar and Date to display a custom module's start and end dates. See full description http://drupal.org/node/1297920.

My solution builds on the above. Hopefully it is useful to others.

Imagine your custom module is called rbookapi and you have a table called rbookapi_bookings with two DATETIME fields start and end, which you want to display on a Calendar View. The following two snippets contain Date, Views (and Calendar?) additions which should be added to your custom module files.

In rbookapi.module (ie. YOURMODULE.module)

/**
 * Tell Views which version you want to you
 */
function rbookapi_views_api() {
	return array(
    'api' => '2.0',
	);
}
/**
 * Tell Date which tables to look for date fields in.
 */
function rbookapi_date_api_tables() {
	return array('rbookapi_bookings');
}

/*
 * Tell Date about your date fields (eg. how they are stored in DB).
 */
function rbookapi_date_api_fields($field) {
	// START FIELD : handles to AND from arrangement
	$values = array(
	// The type of date: DATE_UNIX, DATE_ISO, DATE_DATETIME.
    'sql_type' => DATE_DATETIME, 
	// Timezone handling options: 'none', 'site', 'date', 'utc'.
    'tz_handling' => 'site',
    'fromto' => array('rbookapi_bookings_start','rbookapi_bookings_end'),
	// Array of "table.field" values for related fields that should be
	// loaded automatically in the Views SQL.
	// THIS IS NOT REQUIRED FOR ME
    //'related_fields' => array('rbookapi_bookings.start','rbookapi_bookings.end'),
	// Granularity of this date field's db data.
    'granularity' => array('year', 'month', 'day'),//, 'hour', 'minute', 'second'),
    
	);
	// END FIELD : just tell Date how to read from db, and how to handle TZ
	$values2 = array (
    'sql_type' => DATE_DATETIME, 
    'tz_handling' => 'site',
    );
	
	switch ($field) {
		case 'rbookapi_bookings.start':
			return $values;
		break;		
		case 'rbookapi_bookings.end':
			return $values2;
			break;
	}
}

Then in rbookapi.views.inc (ie YOURMODDULE.views.inc):

/**
 * Tell Views about fields, filters, arguments, etc to use.
 */
function rbookapi_views_data() {

	$data['rbookapi_bookings']['start'] = array(
        'title' => t('Start Date'),
		'group' => t('RBook'),
        'help' => 'Arrival date',
		'field' => array(
  			'handler' => 'views_handler_field_date',  // intuitive views_handler_field_datetime is incorrect here
		),
		'argument' => array(
      		'handler' => 'date_api_argument_handler',  // 
		),
		// Not required for base functionality but probably correct
		 'filter' => array(
        	'handler' => 'date_api_filter_handler'
	)

	);

	$data['rbookapi_bookings']['end'] = array (
        'title' => t('Last Night'),
		'group' => t('RBook'),
        'help' => 'End date is clients last night, not the day after' ,
		'field' => array(
  			'handler' => 'views_handler_field_date', // intuitive views_handler_field_datetime is incorrect here
		),
		'argument' => array(
      		'handler' => 'date_api_argument_handler',  
		),
	);


	$data['rbookapi_bookings']['table']['group']  = t('RBook');

	$data['rbookapi_bookings']['table']['base'] = array (
    'field' => 'booking_id',
    'title' => t('Base Rbook record'),
    'help' => t("RBook base table"),
	);

    // Example of a non-date field
	$data['rbookapi_bookings']['booking_id'] = array (
    'title' => t('Booking ID'),
    'field' => array(
      'handler' => 'views_handler_field_numeric',
      'click sortable' => TRUE,
	)
	);

	return $data;
)
ARUN AK’s picture

Issue summary: View changes

@bbeeson, is it mandatory to declare hook_views_api()?

RoloDMonkey’s picture

@ARUN AK

Yes.