Support from Acquia helps fund testing for Drupal Acquia logo

Comments

johnv’s picture

Status: Active » Needs review
FileSize
7.97 KB

Attached a Feeds mapper for Office Hours.
You can use the following columns: day, hours/morehours from-to, hours/morehours from and hours/morehours to.
The day should be named in full English name, or a day number, where sunday = 0, monday=1, etc.
The hours can be used as hh:mm or hh.mm

I suppose Feeds Tamper can help to format the times and/or day to the proper format.

Here's an exampel file:
nid;weekday;Hours_1;Hours_2
2345;monday;11:00 - 18:01;
2345;tuesday;10:00 - 12:00;13:15-17.45
2383;monday;11:00 - 18:01;
2383;tuesday;10:00 - 12:00;13:15-17.45

johnv’s picture

a better version..

johnv’s picture

yet another better patch..

xmacex’s picture

Totally sweet mate, let's have this in the package please?

johnv’s picture

Workin' on it. Did you check your import thoroughly? In my imports is happens (once and a while) that only 2-3 of 6 days are generated. I cannot figure out what's the cause. It only happens with bigger imports (>30 entities).

johnv’s picture

Status: Needs review » Fixed

Committed to D7.
Perhaps the following line must be removed after Feeds has been fixed in this issue: #1139676: feeds_alter doesn't support hook_module_implements_alter, hook_hook_info and hook_hook_info_alter
module_load_include('inc', 'office_hours', 'office_hours.feeds');

Status: Fixed » Closed (fixed)

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

johnv’s picture

Status: Closed (fixed) » Fixed

The issue as in #6 has been committed to Feeds as of december 2011: #1139676-22: feeds_alter doesn't support hook_module_implements_alter, hook_hook_info and hook_hook_info_alter.
So removed the line with commit 0a7961e.

Status: Fixed » Closed (fixed)

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

aditya.captovate’s picture

Category: feature » support
Status: Closed (fixed) » Active

Have come across an issue whereby only the last csv entry for an entitity is saved. For example, from the following csv, only the value for Sunday is saved

title,weekday,hours_1
assac,monday,08:30 - 16:30
assac,tuesday,08:30 - 16:30
assac,wednesday,08:30 - 16:30
assac,thursday,08:30 - 16:30
assac,friday,08:30 - 16:30
assac,saturday,
assac,sunday,

Ivo.Radulovski’s picture

Category: bug » support

hello, it imports only the last value (overwrites the previous values)

any clue?

nid;weekday;Hours_start;Hours_end
10647;Monday;07:00;19:00
10647;Tuesday;08:00;16:00

Only Tuesday is importedt when i run it like this

using
used Feeds 7.x-2.0-alpha8 and Office Hours 7.x-1.3

Ivo.Radulovski’s picture

Category: support » bug

also this seems to be a bug

vlooivlerke’s picture

I have tried every possible way to import office hours and are only able to import one day and its times. The rest of the week is ignored. Tried some Feeds Tamper but did not work.
I think the Day feed part has a bug.

pozz’s picture

Issue summary: View changes

It seems not work. In Feeds i set Day for "DAY", Hours for "HOUR_1" and More Hours for "HOUR_2"

is it correct? any help?

DAY;HOUR_1;HOUR_2
monday;09:30-12:00;15:00-18:00

johnv’s picture

Version: 7.x-1.x-dev » 7.x-1.3
Category: Support request » Bug report
Status: Active » Fixed

Please try today's dev-version.
The Feeds importer was broken since the latest structure change of the field, which allowed unlimited blocks per day.

Remember, you need to have the 'day' column/field BEFORE the 'hours' or 'morehours' columns/fields.
From now on, you can feed any number of timeblocks per day. There is no difference anymore between 'hours' and 'morehours'.
Just keeping both for backwards compatibility.

Status: Fixed » Closed (fixed)

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

Berliner-dupe’s picture

I tested all for one day for testing....

Day;Hours
1;02:00 - 06:00
Day;Hours
1;02.00 - 06.00
Day;Hours
monday;02:00 - 06:00
Day;Hours
monday;02.00 - 06.00
Day;Hours_start;Hours_end
1;02:00;06:00
Day;Hours_start;Hours_end
1;02.00;06.00
Day;Hours_start;Hours_end
monday;02:00;06:00
Day;Hours_start;Hours_end
monday;02.00;06.00

... but nothing works. The office hour day is ever empty ....

In Feedsmapping i map ......
"Office hour: Day" = Day
"Office hour: Hours" = Hours
or
"Office hour: Hours start" = Hours_start
"Office hour: Hours end" = Hours_end

I use the latest office-hours dev-version and the latest Feeds-dev-version but nothing.

What i make wrong?

Berliner-dupe’s picture

Status: Closed (fixed) » Needs work

  • johnv committed 4061509 on 8.x-1.x
    Issue [#1160440] by johnv : added Feeds support.
    
    
  • johnv committed c2e76a7 on 8.x-1.x
    Issue [#1160440] by johnv : added Feeds support.
    
    
  • johnv committed feb871a on 8.x-1.x
    Issue #1160440 Fixed feeds importer.
    
GerZah’s picture

Re- importing opening times for multiple days:

The problem is that any new CSV line with the same unique field (e.g. NID) will create a new set of opening times during import – which means that even if your feed will update the same node multiple times, ultimately only the last open/close hours will show up (as first reported in #11).


The solution is far from obvious, but simple enough (in my case in good old 7.x-1.3): All opening hours for the different days need to be in one line.
I know that this is a tough precondition; however, as to the nature of Feeds which will update the whole field with every new line of import data, I have no idea how to import multiple open/close constellation for the same node in different lines.

Constructive example: Instead of using something like this

nid;weekday;Hours_start;Hours_end
10647;monday;07:00;19:00
10647;tuesday;08:00;16:00

use something like this:

nid;day1;start1;end1;day2;start2;end2
10647;monday;07:00;19:00;tuesday;08:00;16:00

Then create the following mapping:

nid -> NID
day1 -> Opening Hours: Day (field_opening_hours:day)
open1 -> Opening Hours: Hours start (field_opening_hours:hours:start)
end1 -> Opening Hours: Hours end (field_opening_hours:hours:end)
day2 -> Opening Hours: Day (field_opening_hours:day)
open2 -> Opening Hours: Hours start (field_opening_hours:hours:start)
end2 -> Opening Hours: Hours end (field_opening_hours:hours:end)

Yes – that's correct: Create a second rule for each hours:day, hours:start, and hours:end.

Actually, my input data looks something like this:

nid,open_mon,open_tue,open_wed,open_thu,open_fri,open_sat,open_sun,close_mon,close_tue,close_wed,close_thu,close_fri,close_sat,close_sun
10647,09:00,09:00,09:00,09:00,09:00,09:00,11:00,18:00,21:00,21:00,21:00,21:00,21:00,18:00

This turns out a bit bulky:

nid -> NID

none_mon (inexistent) -> Opening Hours: Day (field_opening_hours:day)
--> tamper: Rewrite -> "monday"
open_mon -> Opening Hours: Hours start (field_opening_hours:hours:start)
close_mon -> Opening Hours: Hours end (field_opening_hours:hours:end)

none_tue (inexistent) -> Opening Hours: Day (field_opening_hours:day)
---> tamper: Rewrite -> "tuesday"
open_tue -> Opening Hours: Hours start (field_opening_hours:hours:start)
close_tue -> Opening Hours: Hours end (field_opening_hours:hours:end)

...

All I can say is: It works this way.

johnv’s picture

Issue summary: View changes

It turns out that the Feeds implementation was developed on a tweaked Feeds module.

IMO The best way is to change the code:
- if a new node starts in the Feeds, Just add the new value
- on any subsequent line for the same node, reload the node from database, take the values and append the new one.

GerZah’s picture

@johnv I don't think so. This is how Feeds handles things. It's similar with multi-val strings: AFAIK, you can't simply add new items during another import for the same unique id: Feeds will always discard the previous content and import the new one (e.g. multiple strings via tamper / explode).

GerZah’s picture

Anyways, another thing regarding my "everything in one line" example in #20:

I'm looking at imports like this:

nid,open_mon,open_tue,open_wed,open_thu,open_fri,open_sat,open_sun,close_mon,close_tue,close_wed,close_thu,close_fri,close_sat,close_sun
10647,09:00,09:00,09:00,09:00,09:00,09:00,NULL,18:00,21:00,21:00,21:00,21:00,21:00,NULL

Meaning: Closed in Sunday.

I tried various things, like replacing "NULL" with an empty value via tamper. But as soon as $sv_day is defined, office_hours.feeds.inc will always carry out intval($feed_element) and thus transforming any non-numeric input to "0" i.e. midnight.


I suggest the following patch

      switch ($start_end_field) {
        case 'start':
            if (!is_numeric($feed_element)) { break; } # <- here
            $entity->{$field_name}[$entity->language][$sv_index]['day'] = $sv_day;
            $entity->{$field_name}[$entity->language][$sv_index]['starthours'] = intval($feed_element);
          break;
        case 'end':
            if (!is_numeric($feed_element)) { break; } # <- here
            $entity->{$field_name}[$entity->language][$sv_index]['day'] = $sv_day;
            $entity->{$field_name}[$entity->language][$sv_index]['endhours'] = intval($feed_element);
          break;
        default:
            // $feed_element contains both Start and End.
            list($hours_start, $hours_end) = explode('-', $feed_element, 2);
            if ( (!is_numeric($hours_start)) or (!is_numeric($hours_end)) ) { break; } # <- here
            $entity->{$field_name}[$entity->language][$sv_index]['day'] = $sv_day;
            $entity->{$field_name}[$entity->language][$sv_index]['starthours'] = intval($hours_start);
            $entity->{$field_name}[$entity->language][$sv_index]['endhours'] = intval($hours_end);
          break;
      }

This way we can actually import entire weeks with closed days. – I've attached the patch file.

troybthompson’s picture

#23 is a lifesaver just when I needed it. Much easier to implement, thank you.

The only issue I seem to be having is if the node had office hours before and the feed changes to all nulls so it's closed every day (because originally it was 00:00-00:00 before the patch), then it's not updating. I don't know if this is a problem of this patch or feeds in general.

GerZah’s picture

@troybthompson It's not? According to my experience, whenever the node with the office hours field is updated, Feeds creates a whole new set of office hours – blank at first, then filled through that (one) CSV line, it will carry only those days that are actually defined.

Mind you, if you are using start / end as single values, both need to be non-numeric. Otherwise, as you have first defined the day field (as instructed in #15), the static variable $sv will be set for that particular day, and either one is_numeric() start or end will define this day.

In other words: Make sure that both start and end will be non-numerical and you should be fine.

troybthompson’s picture

Yes, just tested again. If I have one day's start and end fields as null, it updates and marks it closed correctly. If I have all days null, it seems to ignore them all. That's why I was wondering if it was a feeds issue.

Feeds 7.x-2.0-alpha8 (the new dev method breaks other modules right now), Office Hours 7.x-1.3+20-dev (2014-Oct-24) with your code replacing that section (not patch since it looks like OH dev's feed is different from what you were patching). So maybe it's just my combination. I'm going to be importing everything from scratch so this won't really affect me but may others.

kufeiko’s picture

In a recent project I developed a small module (attached) to import office hours on one-per-line basis, which seems a lot more better.

The imput is a .csv with the following format:

nid,mon,tue
2,10:00 - 18:00,10:00 - 19:00

In Feeds admin interface you will have to map every day to its column.

kufeiko’s picture

finaukaufusi’s picture

I'm trying to use the oh_import module with no success

I'm importing my office hours together with other fields in my node content type.

Question: Do I have to provide the node id (nid)? I thought it should be automatically populate like the other fields.

osman’s picture

@vanko, I found your custom module quite useful, thanks for sharing.

However, my import data includes multiple time spans for each day, and each day are listed in the same row in the CSV file.

i.e.

A B C D E F G H
1
Title Mon Tue Wed Thu Fri Sat Sun
2
Lipsum 1
12:00 pm - 4:00 pm, 07:00 pm - 11:30 pm
12:00 pm - 4:00 pm, 07:00 pm - 11:30 pm
12:00 pm - 4:00 pm, 07:00 pm - 11:30 pm
12:00 pm - 4:00 pm, 07:00 pm - 11:30 pm
12:00 pm - 03:30 pm, 07:00 pm - 01:00 pm
12:00 pm - 03:30 pm, 07:00 pm - 01:00 pm
12:00 pm - 4:00 pm, 07:00 pm - 11:30 pm
3
Lorem 2 12:00 pm - 11:00 pm 12:00 pm - 11:00 pm 12:00 pm - 11:00 pm 12:00 pm - 11:00 pm 12:00 pm - 11:00 pm 12:00 pm - 11:00 pm 12:00 pm - 11:00 pm
4
Another entry 12:30 pm - 10:00 pm 12:30 pm - 10:00 pm 12:30 pm - 10:00 pm 12:30 pm - 10:00 pm 12:30 pm - 10:00 pm 12:30 pm - 10:00 pm 12:30 pm - 10:00 pm

As you can see days are listed as columns and in each column time-spans are separated by a comma.

I made some changes to your code, to support a file similar to this example. I temporarily excluded the update logic you had in place; I think it is a nice feature, btw.

Here is the updated code for importing a dataset similar to above:

/**
 * @file
 * Implementation of Feeds mapping API for office_hours.module.
 */

/**
 * Implements hook_feeds_processor_targets_alter().
 */
function oh_import_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
  foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
    $info = field_info_field($name);
    if ($info['type'] == 'office_hours') {

      $targets[$name . ':mon'] = array(
        'name' => $instance['label'] . ': Monday',
        'callback' => '_day_set_target',
        'description' => t('Monday office hours.'),
        'real_target' => $name,
      );
      $targets[$name . ':tue'] = array(
        'name' => $instance['label'] . ': Tuesday',
        'callback' => '_day_set_target',
        'description' => t('Tuesday office hours.'),
        'real_target' => $name,
      );
      $targets[$name . ':wed'] = array(
        'name' => $instance['label'] . ': Wednesday',
        'callback' => '_day_set_target',
        'description' => t('Wednesday office hours.'),
        'real_target' => $name,
      );
      $targets[$name . ':thu'] = array(
        'name' => $instance['label'] . ': Thursday',
        'callback' => '_day_set_target',
        'description' => t('Thursday office hours.'),
        'real_target' => $name,
      );
      $targets[$name . ':fri'] = array(
        'name' => $instance['label'] . ': Friday',
        'callback' => '_day_set_target',
        'description' => t('Friday office hours.'),
        'real_target' => $name,
      );
      $targets[$name . ':sat'] = array(
        'name' => $instance['label'] . ': Saturday',
        'callback' => '_day_set_target',
        'description' => t('Saturday office hours.'),
        'real_target' => $name,
      );
      $targets[$name . ':sun'] = array(
        'name' => $instance['label'] . ': Sunday',
        'callback' => '_day_set_target',
        'description' => t('Sunday office hours.'),
        'real_target' => $name,
      );
    }
  }
}

/**
 * Sets the target for every day.
 */
function _day_set_target($source, $entity, $target, $value) {
  // Actually, $value is expected to be array.
  if (is_array($value)) {
    $value = $value[0];
  }

  // Get the real field name.
  $field = substr($target, 0, strpos($target, ":"));

  $day_to_num = array(
    'mon' => 1,
    'tue' => 2,
    'wed' => 3,
    'thu' => 4,
    'fri' => 5,
    'sat' => 6,
    'sun' => 0,
  );

  $numday = $day_to_num[substr($target, -3)];

  $time_spans = explode(',', $value);

  if (!empty($time_spans[0])) {
    foreach ($time_spans as $key => $time_span) {
      list($hours_start, $hours_end) = explode('-', $time_span, 2);

      $entity->{$field}['und'][] = array(
        'day' => $numday,
        'starthours' => intval(str_replace(array(' ', ':', '.'), '', date("H:i", strtotime($hours_start)))),
        'endhours' => intval(str_replace(array(' ', ':', '.'), '', date("H:i", strtotime($hours_end)))),
      );
    }
  }

  return $entity;
}
osman’s picture

Status: Needs work » Needs review
kufeiko’s picture

@osman Yes, there are many different scenarios about those imports, so I guess a little tweaking is inevitable :)
Thanks for sharing your code too, so anyone with such problems can benefit from it.

johnv’s picture

Component: Code » Integrating Feeds
johnv’s picture

Version: 7.x-1.3 » 7.x-1.x-dev
Category: Bug report » Feature request
johnv’s picture

Status: Needs review » Closed (outdated)

Given the life cycle of D7, this issue is considered closed. However, patches are appreciated.