Révision 55670b15
Ajouté par Assos Assos il y a presque 10 ans
drupal7/sites/all/modules/date_ical/README.txt | ||
---|---|---|
2 | 2 |
|
3 | 3 |
This module allows users to export iCal feeds using Views, and import iCal feeds |
4 | 4 |
from other sites using Feeds. Any entity that contains a Date field can act as |
5 |
the source of events for an iCal feed. |
|
5 |
the source/target to export/import an iCal feed. |
|
6 |
|
|
6 | 7 |
|
7 | 8 |
=============================================================================== |
8 | 9 |
INSTALLATION |
... | ... | |
15 | 16 |
- The Feeds module is optional. It's needed only if you you wish to import iCal |
16 | 17 |
feeds from other sites. |
17 | 18 |
|
18 |
To install the iCalcreator library, download it from the project's github: |
|
19 |
http://github.com/iCalcreator/iCalcreator |
|
20 |
Using either git clone or the "Download Zip" button, you'll find the file |
|
21 |
iCalcreator.class.php inside. Copy that file to a folder in your Drupal site |
|
22 |
named sites/all/libraries/iCalcreator. |
|
19 |
To install the iCalcreator library, download the project's official zip file: |
|
20 |
https://github.com/iCalcreator/iCalcreator/archive/master.zip |
|
21 |
Extract it, and copy iCalcreator.class.php to a folder in your Drupal site |
|
22 |
named sites/all/libraries/iCalcreator (you'll need to create that folder). |
|
23 | 23 |
|
24 |
Or, if you have drush, install iCalcreator by running this command from your
|
|
25 |
site's root directory: |
|
24 |
Or, if you have drush, you can install iCalcreator by running this command from
|
|
25 |
your site's root directory:
|
|
26 | 26 |
drush make sites/all/modules/date_ical/date_ical.make --no-core |
27 | 27 |
|
28 | 28 |
Then, clear the cache on your site by using either "drush cc all" or logging in |
... | ... | |
56 | 56 |
size, include additional information from other fields, etc. |
57 | 57 |
4. Do this for each of the content types that you wish to include in your |
58 | 58 |
site's iCal feeds. |
59 |
5. Create a new View that displays the entities that you want to include in the |
|
60 |
iCal feed. |
|
61 |
6. Add a "Feed" to the view. Change the Format to "iCal Feed". When you click |
|
62 |
Apply from that dialog, you'll be given the option to name the calendar, |
|
63 |
which will appear in your users' calendar clients as the calendar's title. |
|
59 |
5. Create a new View that displays the entities that you want to include in |
|
60 |
the iCal feed. |
|
61 |
6. Add a "Feed" display to the same View. Change the Format to "iCal Feed". |
|
62 |
When you click "Apply" from that dialog, you'll be given the option to name |
|
63 |
the calendar, which will appear in your users' calendar clients as the |
|
64 |
calendar's title. |
|
64 | 65 |
7. Change the Show setting to "iCal Entity". |
65 | 66 |
8. In the settings for iCal Entity, select the date field that should be used |
66 | 67 |
as the event date for the iCal feed. Make sure that you choose a field that |
67 | 68 |
is a part of every entity that your View displays. Otherwise, the entities |
68 | 69 |
which don't have that field will be left out of the iCal feed. |
69 |
9. You may optionally choose a field that will be used to populate the Location
|
|
70 |
property of events in your iCal feed. This field can be a text field, a
|
|
71 |
Node Reference field, an Addressfield, or a Location field. |
|
72 |
10. Give the feed a path like 'calendar/%/export.ics', including a '/%/' for
|
|
70 |
9. You may optionally choose a field that will be used to populate the |
|
71 |
Location property of events in your iCal feed. This field can be a text
|
|
72 |
field, a Node Reference field, an Addressfield, or a Location field.
|
|
73 |
10. Give the Feed a path like 'calendar/%/export.ics', including a '/%/' for
|
|
73 | 74 |
every contextual filter in the view. |
74 | 75 |
11. Make sure the Pager options are set to "Display all items". |
75 | 76 |
12. Add date filters or arguments that will constrain the view to the items you |
76 | 77 |
want to be included in the iCal feed. |
77 |
13. Attach the feed to a another view (usually a Page view that is displaying |
|
78 |
the same events). Be aware, though, that attaching the feed to a view with |
|
79 |
different output will not make the iCal feed include that output. It will |
|
80 |
always include the events which match the feed's filters. |
|
78 |
13. Using the "Attach to:" setting in the Feed Settings panel, attach the feed |
|
79 |
to a another display in the same view (usually a Page display). Be aware, |
|
80 |
though, that the Feed will display exactly what its settings tell it to, |
|
81 |
regardless of how the Page display is set up. Thus, it's best to ensure |
|
82 |
that both displays are configured to include the same content. |
|
81 | 83 |
14. Save the View. |
82 |
15. Navigate to a page which displays the attached view. You should see the iCal |
|
83 |
icon at the bottom of the view's output. Clicking on the icon will subscribe |
|
84 |
your preferred calendar app to the iCal feed. However, if you don't have a |
|
85 |
calendar app set up on your computer, you'll want to go back to the View |
|
86 |
settings page, click the Settings link next to "Format: iCal Feed", and check |
|
87 |
"Disable webcal://", then save your View. This will make the iCal icon |
|
88 |
download a .ics file with the events, instead of loading the events directly |
|
89 |
into a calendar app. |
|
84 |
15. Navigate to a page which displays the view (usually the Page display's |
|
85 |
"path" setting). You should see the iCal icon at the bottom of the view's |
|
86 |
output. Clicking on the icon will subscribe your calendar app to the iCal |
|
87 |
feed. |
|
88 |
16. If you don't have a calendar app set up on your computer, or you want your |
|
89 |
users to download the ical feed rather than subscribe to it, you'll want to |
|
90 |
go back to the View settings page, click the Settings link next to |
|
91 |
"Format: iCal Feed", and check "Disable webcal://". Then save your View. |
|
92 |
This will make the iCal icon download a .ics file with the events, instead |
|
93 |
of loading the events directly into the user's calendar app. |
|
90 | 94 |
|
91 | 95 |
HOW TO EXPORT AN ICAL FEED USING THE iCal Fields PLUGIN |
92 | 96 |
1-6.These steps are the same as above. |
... | ... | |
94 | 98 |
your iCal feed with. A Date field is required, and fields that will act as |
95 | 99 |
the Title and Description of the events are reccomended. You can also |
96 | 100 |
include a Location field. |
97 |
8. Back in the FORMAT section, change the Show setting to 'iCal Fields'.
|
|
101 |
8. Back in the FORMAT section, change the "Show" setting to 'iCal Fields'.
|
|
98 | 102 |
9. In the settings for iCal Fields, choose which views fields you want to use |
99 | 103 |
for the Date, Title, Description, and Location. |
100 | 104 |
10+ These steps are the same as above. |
... | ... | |
133 | 137 |
you add any more mappings, click "Save" at the bottom of the page. |
134 | 138 |
2) It's a good idea to map the "Summary/Title" source to the "Title" target, |
135 | 139 |
and the "Description" source to whatever field is the "body" of the node. |
136 |
3) As of 2014/02/03 there is a major bug in Feeds that leaves the Date
|
|
137 |
values on all imported events blank. You must update your Feeds module
|
|
138 |
to the dev release (https://drupal.org/node/927032) to overcome this bug.
|
|
140 |
3) AS OF 2014/04/10 THERE IS A MAJOR BUG IN Feeds WHICH LEAVES THE DATE
|
|
141 |
VALUES ON ALL IMPORTED EVENTS BLACNK. YOU MUST APPLY A PATCH TO Feeds
|
|
142 |
TO FIX THIS PROBLEM. IT IS AVAILABLE HERE: http://drupal.org/node/2237177.
|
|
139 | 143 |
- Once you've completed all the mappings, click the "Save" button on the |
140 | 144 |
bottom left side of the page. |
141 | 145 |
- Now you can import the iCal feed into nodes by going to the /import page of |
142 | 146 |
your site (e.g. http://www.exmaple.com/import). Click the link for the |
143 |
importer you just created, and enter the URL of the feed you'd like to |
|
144 |
import into the "URL" field. Click the "Import" button, and observe the |
|
145 |
progress. |
|
147 |
importer you just created, and enter the URL of the feed into the "URL" |
|
148 |
field. Click the "Import" button, and observe the progress. |
|
146 | 149 |
- Once it's done, you should see a green message saying "Created X nodes." If |
147 | 150 |
you do, you've successfully set up your iCal importer. If you get some other |
148 | 151 |
message, you'll need to tweak the importer's settings. |
... | ... | |
150 | 153 |
Remember, you have to map the UID source to the GUID target, and make it |
151 | 154 |
unique, or your imports won't work! |
152 | 155 |
|
153 |
IMPORTANT NOTE: |
|
154 |
If you're building a site that will be viewed by out-of-state users, and you |
|
155 |
allow said users to set their own timezone, you'll want to set up your Date |
|
156 |
fields to use the "Date's time zone" option. If you don't, then users who live |
|
157 |
in a different timezone will be shown the times for your events in their local |
|
158 |
timezone, rather than your events' timezone. This makes sense if your events |
|
159 |
will be broadcast live to these out-of-state users, but if they need to travel |
|
160 |
to your event, they may end up arriving at the wrong time. |
|
156 |
|
|
157 |
=============================================================================== |
|
158 |
IMPORTANT NOTE ABOUT THE DATE FIELD TIMEZONE SETTING |
|
159 |
=============================================================================== |
|
160 |
Date fields have a setting called "Time zone handling" which determines how |
|
161 |
dates are stored in the database, and how they are displayed to users. |
|
162 |
- "Site's time zone" converts the date to UTC as it stores it to the DB. Upon |
|
163 |
display, it converts the date to the "Default time zone" that's set on your |
|
164 |
site's Regional Settings configuration page (/admin/config/regional/settings). |
|
165 |
- "Date's time zone" stores the date as it is entered, along with the timezone |
|
166 |
name. Upon display, it converts the date from the stored timezone into the |
|
167 |
site's default timezone. Well, I'm pretty sure it's *supposed* to do that, but |
|
168 |
the code behind this setting is very buggy. DO NOT USE THIS SETTING. |
|
169 |
- "User's time zone" converts the date to UTC as it stores it to the DB. Upon |
|
170 |
display, it converts the date to the current user's timezone setting. |
|
171 |
- "UTC" converts the date to UTC as it stores it to the DB. Upon display, it |
|
172 |
performs no conversion, showing the UTC date directly to the user. |
|
173 |
- "No time zone conversion" performs no conversion as it stores the date in |
|
174 |
the DB. It also performs no conversion upon display. |
|
175 |
|
|
176 |
The appropriate setting to choose here will depend upon how you want times to |
|
177 |
be displayed on your site. The best setting *would* be "Date's time zone", |
|
178 |
but since that setting is so buggy, I must recommend against it. Instead, |
|
179 |
I'd suggest using "Site's time zone" for sites which host events that are |
|
180 |
mostly in the same timezone (set the site's default timezone appropriately). |
|
181 |
This works just right for local users of your site, and will be the least |
|
182 |
confusing for users who live in a different timezone. |
|
183 |
|
|
184 |
For sites which store events that take place in multiple different timezones, |
|
185 |
the "User's time zone" setting is probably the most appropriate. Most users will |
|
186 |
presumably be tuning in to your events online or on TV (since many take place |
|
187 |
far away from them), which means they'll want to know what time the event occurs |
|
188 |
in their local timezone, so they don't miss the broadcast. |
|
189 |
|
|
190 |
If your Date field is already set to "Date's time zone", you won't be able to |
|
191 |
change it, because that setting uses a different table schema than the others. |
|
192 |
Since "Date's time zone" is very buggy, I'd strongly recomend deleting the |
|
193 |
field and recreating it with a different setting. This will delete all the |
|
194 |
dates in existing event nodes which use this field. |
|
195 |
|
|
161 | 196 |
|
162 | 197 |
=============================================================================== |
163 | 198 |
HOW TO FIX THE "not a valid timezone" ERROR |
... | ... | |
184 | 219 |
Replace <module> with the name of your module, change the code to do whatever |
185 | 220 |
needs to be done to fix your timezones, and clear your Drupal cache. |
186 | 221 |
|
222 |
|
|
187 | 223 |
=============================================================================== |
188 | 224 |
ADDITIONAL NOTES |
189 | 225 |
=============================================================================== |
190 |
Date iCal only supports outputting iCal calendars through Views.
|
|
226 |
Date iCal only supports exporting iCal calendars by using Views.
|
|
191 | 227 |
To put an "Add to calendar" button on individual event nodes, try the |
192 | 228 |
Add to Cal module (http://drupal.org/project/addtocal), or follow the |
193 | 229 |
instructions created by the estimable nmc at: |
drupal7/sites/all/modules/date_ical/date_ical.api.php | ||
---|---|---|
139 | 139 |
*****************************************************************************/ |
140 | 140 |
|
141 | 141 |
/** |
142 |
* Alter the vcalendar object created from an imported iCal feed.
|
|
142 |
* Alter the vcalendar object imported from an iCal feed.
|
|
143 | 143 |
* |
144 | 144 |
* @param object $calendar |
145 | 145 |
* An instance of the iCalcreator library's vcalendar class. |
... | ... | |
153 | 153 |
} |
154 | 154 |
|
155 | 155 |
/** |
156 |
* Alter a calendar component created from an imported iCal feed.
|
|
156 |
* Alter a calendar component imported from an iCal feed.
|
|
157 | 157 |
* |
158 | 158 |
* @param object $component |
159 | 159 |
* This will usually be an iCalcreator vevent object, but Date iCal also |
... | ... | |
174 | 174 |
} |
175 | 175 |
} |
176 | 176 |
|
177 |
/** |
|
178 |
* Alter the parsed data for an event imported from an iCal feed. |
|
179 |
* |
|
180 |
* @param array $data |
|
181 |
* An associative array of field data that represents an imported event. |
|
182 |
* @param array $context |
|
183 |
* An associative array of context, with the following keys and values: |
|
184 |
* - 'calendar': The iCalcreator vcalendar parent object of this component. |
|
185 |
* - 'source': FeedsSource object for this Feed. |
|
186 |
* - 'fetcher_result': The FeedsFetcherResult object for this Feed. |
|
187 |
*/ |
|
188 |
function hook_date_ical_import_post_parse_alter(&$data, $context) { |
|
189 |
// Example of what might be done with this alter hook. |
|
190 |
if (!empty($context['calendar']->xprop['X-WR-CALNAME']['value'])) { |
|
191 |
// Do something with the calendar name.... |
|
192 |
} |
|
193 |
} |
|
194 |
|
|
177 | 195 |
/** |
178 | 196 |
* Alter the timezone string from an imported iCal Feed. |
179 | 197 |
* |
drupal7/sites/all/modules/date_ical/date_ical.info | ||
---|---|---|
21 | 21 |
; Includes for iCal feed import using Feeds |
22 | 22 |
files[] = includes/DateiCalFeedsParser.inc |
23 | 23 |
|
24 |
; Information added by Drupal.org packaging script on 2014-02-04
|
|
25 |
version = "7.x-3.1"
|
|
24 |
; Information added by Drupal.org packaging script on 2014-05-30
|
|
25 |
version = "7.x-3.2"
|
|
26 | 26 |
core = "7.x" |
27 | 27 |
project = "date_ical" |
28 |
datestamp = "1391480015"
|
|
28 |
datestamp = "1401492228"
|
|
29 | 29 |
|
drupal7/sites/all/modules/date_ical/date_ical.module | ||
---|---|---|
10 | 10 |
* value of the iCal feeds created by Date iCal. It's primarily used for |
11 | 11 |
* debugging. |
12 | 12 |
*/ |
13 |
define('DATE_ICAL_VERSION', '3.1');
|
|
13 |
define('DATE_ICAL_VERSION', '3.2');
|
|
14 | 14 |
|
15 | 15 |
/** |
16 | 16 |
* Exception class for generic exceptions thrown by this module. |
... | ... | |
168 | 168 |
'download url' => 'http://github.com/iCalcreator/iCalcreator', |
169 | 169 |
'version arguments' => array( |
170 | 170 |
'file' => 'iCalcreator.class.php', |
171 |
'pattern' => "/define\( 'ICALCREATOR_VERSION', 'iCalcreator ([\d\.]+)' \);/",
|
|
171 |
'pattern' => "/define.*?ICALCREATOR_VERSION.*?([\d\.]+)/",
|
|
172 | 172 |
'lines' => 100, |
173 | 173 |
), |
174 | 174 |
'files' => array( |
drupal7/sites/all/modules/date_ical/date_ical.utils.inc | ||
---|---|---|
42 | 42 |
$start_datetime = date_format($start, DATE_FORMAT_DATETIME); |
43 | 43 |
|
44 | 44 |
if (!empty($rrule_values['UNTIL']['datetime'])) { |
45 |
// TODO: The spec says that UNTIL must be specified in UTC, but I think |
|
46 |
// this may not be followd by all feed creators. It may be a good idea to |
|
47 |
// support optionally assuming the date has the same TZID as DTSTART. |
|
48 |
$end = date_ical_date($rrule_values['UNTIL'], $timezone); |
|
49 |
$end_datetime = date_format($end, DATE_FORMAT_DATETIME); |
|
45 |
// The spec says that UNTIL must be in UTC, but not all feed creators |
|
46 |
// follow that rule. If the user specified that he wanted to overcome this |
|
47 |
// problem, use $timezone for the $final_repeat, and then convert the UNTIL |
|
48 |
// in the unparsed RRULE to UTC. |
|
49 |
if (!empty($source->importer->config['parser']['config']['until_not_utc'])) { |
|
50 |
// Change the parsed UNTIL from UTC to $timezone, so that the |
|
51 |
// date_ical_date() won't convert it. |
|
52 |
$rrule_values['UNTIL']['tz'] = $timezone; |
|
53 |
|
|
54 |
// Convert the unparsed UNTIL to UTC, since the Date code will use it. |
|
55 |
// It may currently have a Z on it, but only because iCalcreator blindly |
|
56 |
// adds one to DATETIME-type UNTILs if it's not there. |
|
57 |
$matches = array(); |
|
58 |
if (preg_match('/^(.*?)UNTIL=([\dT]+)Z?(.*?)$/', $repeat_data['RRULE'], $matches)) { |
|
59 |
// If the UNTIL value doesn't have a "T", it's a DATE, making timezone |
|
60 |
// fixes irrelvant. |
|
61 |
if (strpos($matches[2], 'T') !== FALSE) { |
|
62 |
$until_date = new DateObject($matches[2], $timezone); |
|
63 |
$until_date->setTimezone(new DateTimeZone('UTC')); |
|
64 |
$matches[2] = $until_date->format('Ymd\THis'); |
|
65 |
$repeat_data['RRULE'] = "{$matches[1]}UNTIL={$matches[2]}Z{$matches[3]}"; |
|
66 |
} |
|
67 |
} |
|
68 |
else { |
|
69 |
watchdog('date_ical', 'The RRULE string "%rrule" could not be parsed to fix the UNTIL value. Date repeats may not be calculated correctly.', |
|
70 |
array('%rrule' => $repeat_data['RRULE']), WATCHDOG_WARNING |
|
71 |
); |
|
72 |
} |
|
73 |
} |
|
74 |
$final_repeat = date_ical_date($rrule_values['UNTIL'], $timezone); |
|
75 |
$final_repeat_datetime = date_format($final_repeat, DATE_FORMAT_DATETIME); |
|
50 | 76 |
} |
51 | 77 |
elseif (!empty($rrule_values['COUNT'])) { |
52 |
$end_datetime = NULL;
|
|
78 |
$final_repeat_datetime = NULL;
|
|
53 | 79 |
} |
54 | 80 |
else { |
55 |
// No UNTIL and no COUNT? |
|
81 |
// No UNTIL and no COUNT? This is an illegal RRULE.
|
|
56 | 82 |
return array(); |
57 | 83 |
} |
58 | 84 |
|
... | ... | |
69 | 95 |
$date = date_ical_date($rdate, $timezone); |
70 | 96 |
$additions[] = date_format($date, 'Y-m-d'); |
71 | 97 |
} |
72 |
// TODO: EXRULE. |
|
98 |
|
|
99 |
// TODO: EXRULEs. |
|
73 | 100 |
|
74 | 101 |
$date_repeat_compatible_rrule = "{$repeat_data['RRULE']}\n{$repeat_data['RDATE']}\n{$repeat_data['EXDATE']}"; |
75 |
$calculated_dates = date_repeat_calc($date_repeat_compatible_rrule, $start_datetime, $end_datetime, $exceptions, $timezone, $additions);
|
|
102 |
$calculated_dates = date_repeat_calc($date_repeat_compatible_rrule, $start_datetime, $final_repeat_datetime, $exceptions, $timezone, $additions);
|
|
76 | 103 |
$repeat_dates = array(); |
77 | 104 |
foreach ($calculated_dates as $delta => $date) { |
78 | 105 |
// date_repeat_calc always returns DATE_DATETIME dates, which is |
... | ... | |
114 | 141 |
continue; |
115 | 142 |
} |
116 | 143 |
|
117 |
// These keys never have multiple values.
|
|
144 |
// The following keys never have multiple values.
|
|
118 | 145 |
if (in_array($key, array('UNTIL', 'FREQ', 'INTERVAL', 'COUNT', 'WKST'))) { |
119 | 146 |
if ($key == 'UNTIL') { |
120 | 147 |
// This is a function from the date_api module, not date_ical. |
drupal7/sites/all/modules/date_ical/includes/DateiCalFeedsParser.inc | ||
---|---|---|
34 | 34 |
throw new DateIcalException(t('Parsing the data from %url failed. Please ensure that this URL leads to a valid iCal feed.', array('%url' => $url))); |
35 | 35 |
} |
36 | 36 |
|
37 |
// Total hack to get around iCalcreator's mistreatment of UID "0". |
|
38 |
if (empty($calendar->components[0]->uid) || empty($calendar->components[0]->uid['value'])) { |
|
39 |
$calendar->components[0]->uid = array('value' => 'zero', 'params' => NULL); |
|
40 |
} |
|
41 |
|
|
37 | 42 |
// Allow modules to alter the vcalendar object before we interpret it. |
38 | 43 |
$context = array( |
39 | 44 |
'source' => $source, |
... | ... | |
69 | 74 |
public function sourceDefaults() { |
70 | 75 |
return array( |
71 | 76 |
'indefinite_count' => $this->config['indefinite_count'], |
77 |
'until_not_utc' => $this->config['until_not_utc'], |
|
78 |
'skip_days' => $this->config['skip_days'], |
|
72 | 79 |
); |
73 | 80 |
} |
74 | 81 |
|
... | ... | |
78 | 85 |
public function configDefaults() { |
79 | 86 |
return array( |
80 | 87 |
'indefinite_count' => '52', |
88 |
'until_not_utc' => FALSE, |
|
89 |
'skip_days' => NULL, |
|
81 | 90 |
); |
82 | 91 |
} |
83 | 92 |
|
... | ... | |
98 | 107 |
'#description' => t('Indefinitely repeating events are not supported. The repeat count will instead be set to this number.'), |
99 | 108 |
'#default_value' => $this->config['indefinite_count'], |
100 | 109 |
); |
110 |
$form['until_not_utc'] = array( |
|
111 |
'#title' => t('RRULE UNTILs are not in UTC'), |
|
112 |
'#type' => 'checkbox', |
|
113 |
'#description' => t('Enable this setting if your reccuring events are not repeating the correct number of times. ' . |
|
114 |
'The iCal spec requires that the UNTIL value in an RRULE almost always be specified in UTC, but some iCal feed creators fail to follow that rule ' . |
|
115 |
'(the UNTIL values in those feeds\' RRULEs don\'t end is "Z"). This causes the UNTIL value to be off by several hours, ' . |
|
116 |
'which can cause the repeat calculator to miss or add repeats.'), |
|
117 |
'#default_value' => $this->config['until_not_utc'], |
|
118 |
); |
|
119 |
$form['skip_days'] = array( |
|
120 |
'#title' => t('Skip events more than X days old'), |
|
121 |
'#type' => 'textfield', |
|
122 |
'#size' => 5, |
|
123 |
'#description' => t('Set this value to any positive integer (or 0) to skip events which ended more than that many days before the import. ' . |
|
124 |
'Leave it blank to import all events.'), |
|
125 |
'#default_value' => $this->config['skip_days'], |
|
126 |
); |
|
101 | 127 |
return $form; |
102 | 128 |
} |
103 | 129 |
|
130 |
/** |
|
131 |
* Validation handler for configForm. |
|
132 |
*/ |
|
133 |
public function configFormValidate(&$source_config) { |
|
134 |
if (!preg_match('/^\d+$/', $source_config['skip_days']) && $source_config['skip_days'] !== '') { |
|
135 |
form_set_error('skip_days', 'You must enter a positive integer.'); |
|
136 |
} |
|
137 |
if ($source_config['skip_days'] === '') { |
|
138 |
$source_config['skip_days'] = NULL; |
|
139 |
} |
|
140 |
} |
|
141 |
|
|
104 | 142 |
/** |
105 | 143 |
* Creates the list of mapping sources offered by DateiCalFeedsParser. |
106 | 144 |
*/ |
... | ... | |
127 | 165 |
'date_ical_parse_handler' => 'parseDateTimeProperty', |
128 | 166 |
); |
129 | 167 |
$sources['RRULE'] = array( |
130 |
'name' => t('Repeat Rule'), |
|
168 |
'name' => t('Date: Repeat Rule'),
|
|
131 | 169 |
'description' => t('The RRULE property. Describes when and how often this event should repeat. |
132 | 170 |
The date field for the target node must be configured to support repeating dates, using the Date Repeat Field module (a submodule of Date).'), |
133 | 171 |
'date_ical_parse_handler' => 'parseRepeatProperty', |
drupal7/sites/all/modules/date_ical/includes/date_ical_plugin_style_ical_feed.inc | ||
---|---|---|
410 | 410 |
// Prevent devel module from appending queries to ical export. |
411 | 411 |
$GLOBALS['devel_shutdown'] = FALSE; |
412 | 412 |
|
413 |
drupal_add_http_header('Content-Type', 'text/calendar; charset=utf-8'); |
|
413 |
drupal_add_http_header('Content-Type', 'text/calendar; charset=UTF-8'); |
|
414 |
drupal_add_http_header('Cache-Control', 'no-cache, must-revalidate'); |
|
415 |
drupal_add_http_header('Expires', 'Sat, 26 Jul 1997 05:00:00 GMT'); |
|
414 | 416 |
|
415 | 417 |
// For sites with Clean URLs disabled, the Display's "path" value ends |
416 | 418 |
// up only in the query args, meaning the filename won't be set properly |
drupal7/sites/all/modules/date_ical/libraries/ParserVcalendar.inc | ||
---|---|---|
16 | 16 |
protected $timezones = array(); |
17 | 17 |
protected $xtimezone; |
18 | 18 |
|
19 |
/** |
|
20 |
* The parsed data for the component that's currently being processed. |
|
21 |
* |
|
22 |
* ParserVcalendar parses one component at a time. This array is stored as a |
|
23 |
* property so that each handler can tell what work the previous handlers |
|
24 |
* have already completed on the current component. |
|
25 |
* |
|
26 |
* @var array |
|
27 |
*/ |
|
28 |
protected $parsed_data = array(); |
|
29 |
|
|
19 | 30 |
/** |
20 | 31 |
* Variables used for batch processing. |
21 | 32 |
*/ |
... | ... | |
28 | 39 |
public function __construct($calendar, $source, $fetcher_result, $config) { |
29 | 40 |
$this->calendar = $calendar; |
30 | 41 |
$this->source = $source; |
42 |
$this->mapping_sources = feeds_importer($source->id)->parser->getMappingSources(); |
|
31 | 43 |
$this->fetcherResult = $fetcher_result; |
32 | 44 |
$this->config = $config; |
33 | 45 |
} |
34 |
|
|
46 |
|
|
35 | 47 |
/** |
36 | 48 |
* Parses the vcalendar object into an array of event data arrays. |
37 | 49 |
* |
... | ... | |
42 | 54 |
* Specifies how many components to parse on this run. |
43 | 55 |
* |
44 | 56 |
* @return array |
45 |
* An array of parsed event data keyed by the same strings as the array |
|
46 |
* returned by DateiCalFeedsParser::getiCalMappingSources(). |
|
57 |
* An array of parsed event data keyed by our mapping source property keys. |
|
47 | 58 |
*/ |
48 | 59 |
public function parse($offset, $limit) { |
49 | 60 |
// Sometimes, the feed will set a timezone for every event in the calendar |
... | ... | |
69 | 80 |
$this->timezones[] = $component; |
70 | 81 |
} |
71 | 82 |
|
83 |
// This content array is used by date_ical_import_component_alter() and |
|
84 |
// date_ical_import_parsed_data_alter(). |
|
85 |
$context2 = array( |
|
86 |
'calendar' => $this->calendar, |
|
87 |
'source' => $this->source, |
|
88 |
'fetcher_result' => $this->fetcherResult, |
|
89 |
); |
|
90 |
|
|
72 | 91 |
// Collect each component, so we can batch them properly in the next loop. |
73 | 92 |
$raw_components = array(); |
74 | 93 |
$types = array('VEVENT', 'VTODO', 'VJOURNAL', 'VFREEBUSY', 'VALARM'); |
... | ... | |
76 | 95 |
while ($vcalendar_component = $this->calendar->getComponent($type)) { |
77 | 96 |
// Allow modules to alter the vcalendar component before we parse it |
78 | 97 |
// into a Feeds-compatible data array. |
79 |
$context = array( |
|
80 |
'calendar' => $this->calendar, |
|
81 |
'source' => $this->source, |
|
82 |
'fetcher_result' => $this->fetcherResult, |
|
83 |
); |
|
84 |
drupal_alter('date_ical_import_component', $vcalendar_component, $context); |
|
98 |
drupal_alter('date_ical_import_component', $vcalendar_component, $context2); |
|
85 | 99 |
$raw_components[] = $vcalendar_component; |
86 | 100 |
} |
87 | 101 |
} |
... | ... | |
92 | 106 |
// Parse each raw component in the current batch into a Feeds-compatible |
93 | 107 |
// event data array. |
94 | 108 |
$events = array(); |
95 |
$sources = DateiCalFeedsParser::getiCalMappingSources(); |
|
96 | 109 |
$batch = array_slice($raw_components, $offset, $limit, TRUE); |
97 | 110 |
foreach ($batch as $ndx => $raw_component) { |
98 |
$parsed_component = array(); |
|
99 |
foreach ($sources as $property_key => $data) { |
|
100 |
$handler = $data['date_ical_parse_handler']; |
|
101 |
$parsed_component[$property_key] = $this->$handler($property_key, $raw_component); |
|
111 |
$this->parsed_data = array(); |
|
112 |
foreach ($this->mapping_sources as $property_key => $data) { |
|
113 |
$handler = NULL; |
|
114 |
if (isset($data['date_ical_parse_handler'])) { |
|
115 |
$handler = $data['date_ical_parse_handler']; |
|
116 |
} |
|
117 |
else { |
|
118 |
// This is not one of our sources, so if we don't recognize and |
|
119 |
// support it, we'll have to pass a warning to the user. |
|
120 |
if ($property_key == 'geofield') { |
|
121 |
$handler = 'parseGeofield'; |
|
122 |
} |
|
123 |
else { |
|
124 |
// We can safely ignore certain sources. |
|
125 |
$known_unknowns = array( |
|
126 |
// "Black Source 1" is from Feeds Tamper. |
|
127 |
'Blank source 1', |
|
128 |
); |
|
129 |
if (!in_array($property_key, $known_unknowns)) { |
|
130 |
// Only warn the user if this mapping source is in use. |
|
131 |
foreach ($this->source->importer->processor->config['mappings'] as $mapping) { |
|
132 |
if ($mapping['source'] == $property_key) { |
|
133 |
drupal_set_message(t('Date iCal does not recognize the "@name" Mapping Source, and must skip it.', array('@name' => $data['name'])), 'warning', FALSE); |
|
134 |
break; |
|
135 |
} |
|
136 |
} |
|
137 |
} |
|
138 |
} |
|
139 |
} |
|
140 |
if ($handler) { |
|
141 |
$this->parsed_data[$property_key] = $this->$handler($property_key, $raw_component); |
|
142 |
} |
|
143 |
|
|
144 |
if ($property_key == 'geofield' && !empty($this->parsed_data['geofield'])) { |
|
145 |
// To make our data readable by geofield_feeds_combined_source(), we |
|
146 |
// need to put it into the format output by Simplepie 1.3. |
|
147 |
$this->parsed_data['location_latitude'] = array($this->parsed_data['geofield']['lat']); |
|
148 |
$this->parsed_data['location_longitude'] = array($this->parsed_data['geofield']['lon']); |
|
149 |
} |
|
150 |
} |
|
151 |
|
|
152 |
// Allow modules to alter the final parsed data before we send it to the |
|
153 |
// Feeds processor. |
|
154 |
drupal_alter('date_ical_import_post_parse', $this->parsed_data, $context2); |
|
155 |
|
|
156 |
// Skip this event if it's earlier than the user's specified skip time. |
|
157 |
if (!$this->_skip_current_event()) { |
|
158 |
$events[] = $this->parsed_data; |
|
102 | 159 |
} |
103 |
$events[] = $parsed_component; |
|
104 | 160 |
// The indices of the original $raw_components array are preserved in |
105 | 161 |
// $batch, so using the $ndx value here lets us communicate our progress |
106 | 162 |
// through the full collection of components. |
... | ... | |
125 | 181 |
} |
126 | 182 |
|
127 | 183 |
/** |
128 |
* Parses text fields.
|
|
184 |
* Handler that parses text fields.
|
|
129 | 185 |
* |
130 | 186 |
* @return string |
131 | 187 |
* The parsed text property. |
... | ... | |
144 | 200 |
$text = str_replace(array('\n', '\N'), "\n", $text); |
145 | 201 |
return $text; |
146 | 202 |
} |
147 |
|
|
203 |
|
|
148 | 204 |
/** |
149 |
* Parses field parameters. |
|
205 |
* Handler that parses GEO fields. |
|
206 |
* |
|
207 |
* @return array |
|
208 |
* The latitude and longitude values, keyed by 'lat' and 'lon'. |
|
209 |
*/ |
|
210 |
public function parseGeofield($property_key, $vcalendar_component) { |
|
211 |
$geo = array(); |
|
212 |
if (!empty($vcalendar_component->geo['value'])) { |
|
213 |
$geo['lat'] = $vcalendar_component->geo['value']['latitude']; |
|
214 |
$geo['lon'] = $vcalendar_component->geo['value']['longitude']; |
|
215 |
} |
|
216 |
return $geo; |
|
217 |
} |
|
218 |
|
|
219 |
/** |
|
220 |
* Handler that parses field parameters. |
|
150 | 221 |
* |
151 | 222 |
* @return string |
152 | 223 |
* The parsed field parameter. |
... | ... | |
158 | 229 |
// If the component doesn't have this property, return NULL. |
159 | 230 |
return NULL; |
160 | 231 |
} |
161 |
return isset($property['params'][$attr]) ? $property['params'][$attr] : ''; |
|
232 |
$param = isset($property['params'][$attr]) ? $property['params'][$attr] : ''; |
|
233 |
return $param; |
|
162 | 234 |
} |
163 |
|
|
235 |
|
|
164 | 236 |
/** |
165 |
* Parses DATE-TIME and DATE fields.
|
|
237 |
* Handler that parses DATE-TIME and DATE fields.
|
|
166 | 238 |
* |
167 | 239 |
* @return FeedsDateTime |
168 | 240 |
* The parsed datetime object. |
... | ... | |
199 | 271 |
// If this is an all-day event with no end or duration, treat this |
200 | 272 |
// as a single-day event by emulating DTEND as 1 day after DTSTART. |
201 | 273 |
$property = $dtstart; |
202 |
$property['value']['day'] = $dtstart['value']['day'] + 1;
|
|
274 |
$property['value'] = iCalUtilityFunctions::_duration2date($property['value'], array('day' => 1));
|
|
203 | 275 |
} |
204 | 276 |
else { |
205 | 277 |
// This event has no end date. |
... | ... | |
239 | 311 |
$property['value'] = $prev_day; |
240 | 312 |
} |
241 | 313 |
} |
242 |
|
|
314 |
|
|
243 | 315 |
// FeedsDateTime->setTimezone() ignores timezone changes made to dates |
244 | 316 |
// with no time element, which means we can't compensate for the Date |
245 | 317 |
// module's automatic timezone conversion when it writes to the DB. To |
... | ... | |
290 | 362 |
$datetimezone = new DateTimeZone(date_default_timezone_get()); |
291 | 363 |
} |
292 | 364 |
} |
293 |
|
|
294 |
return new FeedsDateTime($date_string, $datetimezone); |
|
365 |
|
|
366 |
$datetime = new FeedsDateTime($date_string, $datetimezone); |
|
367 |
return $datetime; |
|
295 | 368 |
} |
296 |
|
|
369 |
|
|
297 | 370 |
/** |
298 |
* Parses multi-value fields, like the CATEGORIES component.
|
|
371 |
* Handler that parses multi-value fields, like the CATEGORIES component.
|
|
299 | 372 |
* |
300 | 373 |
* @return array |
301 | 374 |
* An array of strings contaning the individual values. |
... | ... | |
316 | 389 |
} |
317 | 390 |
return $property; |
318 | 391 |
} |
319 |
|
|
392 |
|
|
320 | 393 |
/** |
321 |
* Format RRULEs, which specify when and how often the event is repeated.
|
|
394 |
* Handler that parses RRULE, RDATE, EXRULE, and EXDATE together.
|
|
322 | 395 |
* |
323 | 396 |
* @return string |
324 |
* An RRULE string, with EXDATE and RDATE values separated by \n. |
|
325 |
* This is to make the RRULE compatible with date_repeat_split_rrule(). |
|
397 |
* The RRULE, RDATE, EXRULE, and EXDATE values concatinated with |. |
|
326 | 398 |
*/ |
327 | 399 |
public function parseRepeatProperty($property_key, $vcalendar_component) { |
328 | 400 |
if ($vcalendar_component->getProperty($property_key) === FALSE) { |
329 | 401 |
return NULL; |
330 | 402 |
} |
331 |
|
|
403 |
|
|
404 |
$uid = $vcalendar_component->getProperty('UID'); |
|
405 |
$count = $this->config['indefinite_count']; |
|
332 | 406 |
// Due to a few bugs and limitations with Date Repeat, we need to massage |
333 | 407 |
// the RRULE a bit. |
334 | 408 |
if (count($vcalendar_component->rrule) > 1) { |
335 |
drupal_set_message(t('The event with UID %uid has multiple RRULEs, but the Date Repeat module only supports one. Only the first RRULE in the event will be used.<br> |
|
336 |
If your events need to have a complex repeat pattern, using RDATEs should help.', |
|
337 |
array('%uid' => $vcalendar_component->getProperty('UID'))), 'warning' |
|
338 |
); |
|
409 |
$msg = 'The event with UID %uid has multiple RRULEs, but the Date Repeat module only supports one. Only the first RRULE in the event will be used. |
|
410 |
If your events need to have a complex repeat pattern, using RDATEs should help.'; |
|
411 |
watchdog('date_ical', $msg, array('%uid' => $uid), 'warning'); |
|
412 |
drupal_set_message('At least one of the events in this iCal feed has multiple RRULEs, but the Date Repeat module only supports one. |
|
413 |
Only the first RRULE in an event will be used.', 'warning', FALSE); |
|
414 |
|
|
339 | 415 |
// Date Repeat will get extremely confused if it's sent multiple RRULE |
340 | 416 |
// values, so we need to manually pare it down to only the first one. |
341 | 417 |
$vcalendar_component->rrule = array($vcalendar_component->rrule[0]); |
... | ... | |
345 | 421 |
if (!isset($rrule_data['value']['INTERVAL'])) { |
346 | 422 |
$rrule_data['value']['INTERVAL'] = '1'; |
347 | 423 |
} |
348 |
|
|
424 |
|
|
349 | 425 |
if (!isset($rrule_data['value']['COUNT']) && !isset($rrule_data['value']['UNTIL'])) { |
350 |
drupal_set_message(t("The event with UID %uid has an indefinitely repeating RRULE, which the Date Repeat module doesn't support.<br> |
|
426 |
$msg = "The event with UID %uid has an indefinitely repeating RRULE, which the Date Repeat module doesn't support. |
|
427 |
As a workaround, Date iCal set the repeat count to @count. This value can be customized in the iCal parser settings."; |
|
428 |
watchdog('date_ical', $msg, array('%uid' => $uid, '@count' => $count), WATCHDOG_WARNING); |
|
429 |
drupal_set_message( |
|
430 |
t("At least one of the events in this iCal feed has an indefinitely repeating RRULE, which the Date Repeat module doesn't support.<br> |
|
351 | 431 |
As a workaround, Date iCal set the repeat count to @count. This value can be customized in the iCal parser settings.", |
352 |
array('%uid' => $vcalendar_component->getProperty('UID'), '@count' => $this->config['indefinite_count'])), 'warning' |
|
432 |
array('@count' => $count)), |
|
433 |
'warning', |
|
434 |
FALSE |
|
353 | 435 |
); |
354 | 436 |
$rrule_data['value']['COUNT'] = $this->config['indefinite_count']; |
355 | 437 |
} |
356 | 438 |
} |
357 |
|
|
439 |
|
|
358 | 440 |
$rrule = trim($vcalendar_component->createRrule()); |
359 | 441 |
$rdate = trim($vcalendar_component->createRdate()); |
360 | 442 |
$exrule = trim($vcalendar_component->createExrule()); |
361 | 443 |
$exdate = trim($vcalendar_component->createExdate()); |
362 | 444 |
return "$rrule|$rdate|$exrule|$exdate"; |
363 | 445 |
} |
364 |
|
|
446 |
|
|
365 | 447 |
/** |
366 | 448 |
* Internal helper function for creating DateTimeZone objects. |
367 | 449 |
*/ |
... | ... | |
377 | 459 |
$windows_to_olson_map = array(); |
378 | 460 |
foreach ($zones_assoc['supplemental']['windowsZones']['mapTimezones'] as $mapTimezone) { |
379 | 461 |
if ($mapTimezone['mapZone']['_other'] == $tzid) { |
380 |
// $mapTimezone['mapZone']['_type'] is space-separated TZIDs.
|
|
462 |
// Parse out the space-separated TZIDs from $mapTimezone['mapZone']['_type'].
|
|
381 | 463 |
$tzids = preg_split('/\s/', $mapTimezone['mapZone']['_type']); |
382 | 464 |
try { |
383 | 465 |
// They all have the same UTC offset, so for our purposes we can |
... | ... | |
405 | 487 |
} |
406 | 488 |
return $datetimezone; |
407 | 489 |
} |
490 |
|
|
491 |
/** |
|
492 |
* Internal helper function for skipping old events. |
|
493 |
*/ |
|
494 |
protected function _skip_current_event() { |
|
495 |
// Must use !isset() here, because 0 and NULL mean different things. |
|
496 |
if (!isset($this->config['skip_days'])) { |
|
497 |
return FALSE; |
|
498 |
} |
|
499 |
$compare_date = isset($this->parsed_data['DTEND']) ? $this->parsed_data['DTEND'] : $this->parsed_data['DTSTART']; |
|
500 |
$skip_date = new FeedsDateTime("today -{$this->config['skip_days']} days", $compare_date->getTimezone()); |
|
501 |
$skip = ($skip_date > $compare_date); |
|
502 |
return $skip; |
|
503 |
} |
|
408 | 504 |
} |
drupal7/sites/all/modules/date_ical/tests/basic_tests.ics | ||
---|---|---|
132 | 132 |
DESCRIPTION:This event uses a fake TZID and should throw the "not a valid timezone" warning at import time, and be treated as UTC. |
133 | 133 |
END:VEVENT |
134 | 134 |
|
135 |
BEGIN:VEVENT |
|
136 |
SUMMARY:Event w/ GEO |
|
137 |
DTSTART;TZID=America/New_York:20131009T190000 |
|
138 |
DTEND;TZID=America/New_York:20131009T210000 |
|
139 |
UID:date_ical_basic_test0E |
|
140 |
DESCRIPTION:This is a standard event that has a GEO field. |
|
141 |
GEO:34.1378534;-118.1252851 |
|
142 |
END:VEVENT |
|
143 |
|
|
135 | 144 |
END:VALENDAR |
drupal7/sites/all/modules/date_ical/tests/until_tests.ics | ||
---|---|---|
1 |
BEGIN:VCALENDAR |
|
2 |
PRODID:-//Google Inc//Google Calendar 70.9054//EN |
|
3 |
VERSION:2.0 |
|
4 |
CALSCALE:GREGORIAN |
|
5 |
METHOD:PUBLISH |
|
6 |
X-WR-CALNAME:Events Feed |
|
7 |
X-WR-TIMEZONE:America/New_York |
|
8 |
X-WR-CALDESC:A calendar for the events feed |
|
9 |
|
|
10 |
BEGIN:VTIMEZONE |
|
11 |
TZID:America/New_York |
|
12 |
X-LIC-LOCATION:America/New_York |
|
13 |
BEGIN:DAYLIGHT |
|
14 |
TZOFFSETFROM:-0500 |
|
15 |
TZOFFSETTO:-0400 |
|
16 |
TZNAME:EDT |
|
17 |
DTSTART:19700308T020000 |
|
18 |
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU |
|
19 |
END:DAYLIGHT |
|
20 |
BEGIN:STANDARD |
|
21 |
TZOFFSETFROM:-0400 |
|
22 |
TZOFFSETTO:-0500 |
|
23 |
TZNAME:EST |
|
24 |
DTSTART:19701101T020000 |
|
25 |
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU |
|
26 |
END:STANDARD |
|
27 |
END:VTIMEZONE |
|
28 |
|
|
29 |
BEGIN:VEVENT |
|
30 |
SUMMARY:Event w/ Bad UNTIL |
|
31 |
UID:12345acbdef1 |
|
32 |
DTSTART;TZID=America/Los_Angeles:20140323T190000 |
|
33 |
DTEND;TZID=America/Los_Angeles:20140323T210000 |
|
34 |
RRULE:FREQ=DAILY;UNTIL=20140328T190000;WKST=SU |
|
35 |
DESCRIPTION:description |
|
36 |
END:VEVENT |
|
37 |
|
|
38 |
BEGIN:VEVENT |
|
39 |
SUMMARY:Event w/ UTC UNTIL |
|
40 |
UID:12345acbdef2 |
|
41 |
DTSTART;TZID=America/Los_Angeles:20140323T190000 |
|
42 |
DTEND;TZID=America/Los_Angeles:20140323T210000 |
|
43 |
RRULE:FREQ=DAILY;UNTIL=20140328T230000Z;WKST=SU |
|
44 |
DESCRIPTION:description |
|
45 |
END:VEVENT |
|
46 |
|
|
47 |
BEGIN:VEVENT |
|
48 |
SUMMARY:Event w/ COUNT |
|
49 |
UID:12345acbdef3 |
|
50 |
DTSTART;TZID=America/Los_Angeles:20140323T190000 |
|
51 |
DTEND;TZID=America/Los_Angeles:20140323T210000 |
|
52 |
RRULE:FREQ=DAILY;COUNT=6;WKST=SU |
|
53 |
DESCRIPTION:description |
|
54 |
END:VEVENT |
|
55 |
|
|
56 |
BEGIN:VEVENT |
|
57 |
SUMMARY:Event w/ DATE-type UNTIL |
|
58 |
UID:12345acbdef4 |
|
59 |
DTSTART;VALUE=DATE:20140323 |
|
60 |
DTEND;VALUE=DATE:20140323 |
|
61 |
RRULE:FREQ=DAILY;UNTIL=20140328;WKST=SU |
|
62 |
DESCRIPTION:description |
|
63 |
END:VEVENT |
|
64 |
|
|
65 |
END:VALENDAR |
drupal7/sites/all/modules/honeypot/honeypot.info | ||
---|---|---|
6 | 6 |
|
7 | 7 |
files[] = honeypot.test |
8 | 8 |
|
9 |
; Information added by Drupal.org packaging script on 2013-12-14
|
|
10 |
version = "7.x-1.16"
|
|
9 |
; Information added by Drupal.org packaging script on 2014-05-30
|
|
10 |
version = "7.x-1.17"
|
|
11 | 11 |
core = "7.x" |
12 | 12 |
project = "honeypot" |
13 |
datestamp = "1386996205"
|
|
13 |
datestamp = "1401478128"
|
|
14 | 14 |
|
drupal7/sites/all/modules/honeypot/honeypot.module | ||
---|---|---|
91 | 91 |
} |
92 | 92 |
} |
93 | 93 |
|
94 |
/** |
|
95 |
* Implements hook_trigger_info(). |
|
96 |
*/ |
|
97 |
function honeypot_trigger_info() { |
|
98 |
return array( |
|
99 |
'honeypot' => array( |
|
100 |
'honeypot_reject' => array( |
|
101 |
'label' => t('Honeypot rejection'), |
|
102 |
), |
|
103 |
), |
|
104 |
); |
|
105 |
} |
|
106 |
|
|
107 |
/** |
|
108 |
* Implements hook_rules_event_info() |
|
109 |
*/ |
|
110 |
function honeypot_rules_event_info() { |
|
111 |
return array( |
|
112 |
'honeypot_reject' => array( |
|
113 |
'label' => t('Honeypot rejection'), |
|
114 |
'group' => t('Honeypot'), |
|
115 |
'variables' => array( |
|
116 |
'form_id' => array( |
|
117 |
'type' => 'text', |
|
118 |
'label' => t('Form ID of the form the user was disallowed from submitting.'), |
|
119 |
), |
|
120 |
// Don't provide 'uid' in context because it is available as |
|
121 |
// site:current-user:uid. |
|
122 |
'type' => array( |
|
123 |
'type' => 'text', |
|
124 |
'label' => t('String indicating the reason the submission was blocked.'), |
|
125 |
), |
|
126 |
), |
|
127 |
), |
|
128 |
); |
|
129 |
} |
|
130 |
|
|
94 | 131 |
/** |
95 | 132 |
* Build an array of all the protected forms on the site, by form_id. |
96 | 133 |
* |
... | ... | |
223 | 260 |
// If not, throw an error. |
224 | 261 |
if (time() < ($honeypot_time + $time_limit)) { |
225 | 262 |
_honeypot_log($form_state['values']['form_id'], 'honeypot_time'); |
226 |
$time_limit = honeypot_get_time_limit(); |
|
263 |
// Get the time limit again, since it increases after first failure. |
|
264 |
$time_limit = honeypot_get_time_limit($form_state['values']); |
|
227 | 265 |
$form_state['values']['honeypot_time'] = time(); |
228 | 266 |
form_set_error('', t('There was a problem with your form submission. Please wait @limit seconds and try again.', array('@limit' => $time_limit))); |
229 | 267 |
} |
... | ... | |
275 | 313 |
))->fetchField(); |
276 | 314 |
} |
277 | 315 |
// Don't add more than 30 days' worth of extra time. |
278 |
$honeypot_time_limit = $honeypot_time_limit + (int) min($honeypot_time_limit + exp($number), 2592000);
|
|
316 |
$honeypot_time_limit = (int) min($honeypot_time_limit + exp($number) - 1, 2592000);
|
|
279 | 317 |
$additions = module_invoke_all('honeypot_time_limit', $honeypot_time_limit, $form_values, $number); |
280 | 318 |
if (count($additions)) { |
281 | 319 |
$honeypot_time_limit += array_sum($additions); |
... | ... | |
313 | 351 |
|
314 | 352 |
// Allow other modules to react to honeypot rejections. |
315 | 353 |
module_invoke_all('honeypot_reject', $form_id, $user->uid, $type); |
354 |
|
|
355 |
// Trigger honeypot_reject action. |
|
356 |
if (module_exists('trigger')) { |
|
357 |
$aids = trigger_get_assigned_actions('honeypot_reject'); |
|
358 |
$context = array( |
|
359 |
'group' => 'honeypot', |
|
360 |
'hook' => 'honeypot_reject', |
|
361 |
'form_id' => $form_id, |
|
362 |
// Do not provide $user in context because it is available as a global. |
|
363 |
'type' => $type, |
|
364 |
); |
|
365 |
// Honeypot does not act on any specific object. |
|
366 |
$object = NULL; |
|
367 |
actions_do(array_keys($aids), $object, $context); |
|
368 |
} |
|
369 |
|
|
370 |
// Trigger rules honeypot_reject event. |
|
371 |
if (module_exists('rules')) { |
|
372 |
rules_invoke_event('honeypot_reject', $form_id, $type); |
|
373 |
} |
|
316 | 374 |
} |
drupal7/sites/all/modules/honeypot/honeypot.test | ||
---|---|---|
98 | 98 |
$this->drupalPost('user/register', $edit, t('Create new account')); |
99 | 99 |
|
100 | 100 |
// Form should have error message. |
101 |
$this->assertText(t('There was a problem with your form submission. Please wait'), 'Registration form protected by time limit.'); |
|
101 |
$this->assertText(t('There was a problem with your form submission. Please wait 6 seconds and try again.'), 'Registration form protected by time limit.');
|
|
102 | 102 |
} |
103 | 103 |
|
104 | 104 |
/** |
... | ... | |
170 | 170 |
$this->assertNoText(t('There was a problem with your form submission.'), 'Honeypot not blocking node form previews.'); |
171 | 171 |
} |
172 | 172 |
} |
173 |
|
|
174 |
/** |
|
175 |
* Test the functionality of the Honeypot module's integration with Trigger. |
|
176 |
*/ |
|
177 |
class HoneypotTriggerTestCase extends DrupalWebTestCase { |
|
178 |
public static function getInfo() { |
|
179 |
return array( |
|
180 |
'name' => 'Honeypot Trigger integration', |
|
181 |
'description' => 'Ensure that Honeypot triggers events correctly.', |
|
182 |
'group' => 'Form API', |
|
183 |
); |
|
184 |
} |
|
185 |
|
|
186 |
public function setUp() { |
|
187 |
// Enable modules required for this test. |
|
188 |
parent::setUp(array('honeypot', 'trigger')); |
|
189 |
|
|
190 |
// Set up required Honeypot variables. |
|
191 |
variable_set('honeypot_element_name', 'url'); |
|
192 |
// Disable time_limit protection. |
|
193 |
variable_set('honeypot_time_limit', 0); |
|
194 |
// Test protecting all forms. |
|
195 |
variable_set('honeypot_protect_all_forms', TRUE); |
|
196 |
variable_set('honeypot_log', FALSE); |
|
197 |
|
|
198 |
// Set up other required variables. |
|
199 |
variable_set('user_email_verification', TRUE); |
|
200 |
variable_set('user_register', USER_REGISTER_VISITORS); |
|
201 |
|
|
202 |
// Assign new action to Honeypot form rejection Trigger. |
|
203 |
db_insert('trigger_assignments') |
|
204 |
->fields(array( |
|
205 |
'hook' => 'honeypot_reject', |
|
206 |
'aid' => 'system_block_ip_action', |
|
207 |
'weight' => 1, |
|
208 |
)) |
|
209 |
->execute(); |
|
210 |
} |
|
211 |
|
|
212 |
/** |
|
213 |
* Test trigger integration. |
|
214 |
*/ |
|
215 |
public function testHoneypotTriggerIntegration() { |
|
216 |
// Set up form and submit it. |
|
217 |
$edit['name'] = $this->randomName(); |
|
218 |
$edit['mail'] = $edit['name'] . '@example.com'; |
|
219 |
$edit['url'] = 'http://www.example.com/'; |
|
220 |
$this->drupalPost('user/register', $edit, t('Create new account')); |
|
221 |
|
|
222 |
// Make sure Honeypot is working. |
|
223 |
$this->assertText(t('There was a problem with your form submission.'), 'Honeypot working correctly.'); |
|
224 |
|
|
225 |
// Visit the home page and make sure the user is banned. |
|
226 |
$this->drupalGet('node'); |
|
227 |
$this->assertText(t('has been banned'), 'User banned successfully.'); |
|
228 |
} |
|
229 |
} |
Formats disponibles : Unified diff
Weekly update of contrib modules