forked from kalebheitzman/grav-plugin-events
-
Notifications
You must be signed in to change notification settings - Fork 11
/
events.php
392 lines (346 loc) · 11.2 KB
/
events.php
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
<?php
/**
* __ __
* / /_ _________ _____ ____/ /_____________
* / __ \/ ___/ __ `/ __ \/ __ / ___/ ___/ __ \
* / /_/ / / / /_/ / / / / /_/ / / / /__/ /_/ /
* /_.___/_/ \__,_/_/ /_/\__,_/_/ \___/\____/
*
* Designed + Developed
* by Kaleb Heitzman
* https://brandr.co
*
* (c) 2016
*/
namespace Grav\Plugin;
// import classes
require_once __DIR__.'/vendor/autoload.php';
require_once __DIR__.'/classes/iCalendarProcessor.php';
require_once __DIR__.'/classes/calendarProcessor.php';
require_once __DIR__.'/classes/eventsProcessor.php';
use Grav\Common\Flex\Types\Pages\PageObject;
use Grav\Common\Page\Header;
use Grav\Common\Plugin;
use Grav\Common\Grav;
use RocketTheme\Toolbox\Event\Event;
use Carbon\Carbon;
/**
* Grav Events
*
* The Events Plugin provides Event Listings and Calendars for your Grav
* powered website. This plugin searches each page for `event:` frontmatter
* and then sets a custom taxonomy named *type* to *event*. It also sets
* a repeating and frequency taxonomy to build more intricate collections.
* The `event_repeat` taxonomy will take a string in the format `MTWRFSU` and
* the `event_freq` taxonomy will take `daily, weekly, monthly, or yearly`.
* These taxonomies are automatically added and processed by the plugin.
*
* Below is a sample of what an `event:` front matter section would look like in
* a Grav page. Note: You can used the event template and yaml included in the
* plugin for use in the admin plugin or add `event:` frontmatter to any page of
* your choice. This plugin is smart enough to add any page to `@taxonomy.type`
* as an event so you can build collections off of pages taxonomized with the
* __event__ taxonomy type.
*
* ```
* event:
* start: 01/01/2015 6:00pm
* end: 01/01/2015 7:00pm
* repeat: MTWRFSU
* freq: weekly
* until: 01/01/2020
* location: Raleigh, NC
* coordinates: 35.7795897, -78.6381787
* ```
*
* If you use the Admin pluin, the events plugin will automatically geo-decode
* the location field to a set of coordinates so that you don't have too.
*
* PHP version 5.6+
*
* @package Events
* @author Kaleb Heitzman <kalebheitzman@gmail.com>
* @copyright 2016 Kaleb Heitzman
* @license https://opensource.org/licenses/MIT MIT
* @version 1.1.0
* @link https://github.com/kalebheitzman/grav-plugin-events
* @since 1.0.0 Initial Release
*/
class EventsPlugin extends Plugin
{
/**
* Current Carbon DateTime
*
* @since 1.0.0 Initial Release
* @var object Carbon DateTime
*/
protected $now;
/**
* Events/Events Class
*
* Processes pages for `event:` frontmatter and then inserts repeating and
* reoccuring events into Grav Pages with updated dates, route, and path.
*
* @since 1.0.0 Initial Release
* @var object Events
*/
protected $events;
/**
* Events/Calendar Class
*
* Provides data to be used in the `calendar.html.twig` template.
*
* @since 1.0.0 Initial Release
* @var object Calendar
*/
protected $calendar;
/**
* Get Subscribed Events
*
* @since 1.0.0 Initial Release
* @return array
*/
public static function getSubscribedEvents()
{
return [
'onPluginsInitialized' => ['onPluginsInitialized', 0],
'onGetPageTemplates' => ['onGetPageTemplates', 0],
'onTwigExtensions' => ['onTwigExtensions', 0],
];
}
/**
* Initialize plugin configuration
*
* Determine if the plugin should run and set the custom
* taxonomies to store event information in. We also initialize the Events
* and Calendar class that this plugin utilizes and then we start
* intercepting Grav hooks to build our events list and insert any vars
* we need into the system.
*
* @since 1.0.0 Initial Release
* @return void
*/
public function onPluginsInitialized()
{
// Nothing else is needed for admin so close it out
if ( $this->isAdmin() ) {
$this->enable([
'onAdminSave' => ['onAdminSave', 0],
]);
return;
}
// Add these to taxonomy for events management
$event_taxonomies = array('type', 'event_freq', 'event_repeat', 'event_location');
$taxonomy_config = array_merge((array)$this->config->get('site.taxonomies'), $event_taxonomies);
$this->config->set('site.taxonomies', $taxonomy_config);
// get the current datetime with c
$this->now = Carbon::now();
// set the calendar accessor
$this->calendar = new \Events\CalendarProcessor();
// set the events accessor
$this->events = new \Events\EventsProcessor();
// enable the following hooks
$this->enable([
'onTwigTemplatePaths' => ['onTwigTemplatePaths', 0],
'onPagesInitialized' => ['onPagesInitialized', 0],
'onTwigSiteVariables' => ['onTwigSiteVariables', 0],
]);
}
/**
* Add current directory to twig lookup paths.
*
* Add the templates directory to the twig directory look up path so we
* can load our page templates. These are overridable by the theme and
* are only meant as a starting point.
*
* @since 1.0.0 Initial Release
* @return void
*/
public function onTwigTemplatePaths()
{
// add templates to twig path
$this->grav['twig']->twig_paths[] = __DIR__ . '/templates';
}
/**
* Add repeating and reoccuring events as Grav pages
*
* Repeating Events: events the tile horizontally in a week `MTWRFSU`
* Reoccuring Events: events that tile vertically through `daily, weekly,
* monthly, yearly`
*
* The Events/Events class searches for pages with `event:` frontmatter and
* processes these into new Grav pages as needed. This is a dynamic operation
* and does not add new physical pages to the filesystem.
*
* @since 1.0.0 Initial Release
* @return void
*/
public function onPagesInitialized()
{
// get instances of all events
$this->events->all();
}
/**
* Association with page templates
*
* @param Event $event
* @since 1.0.15 Major Refactor
* @return void
*/
public function onGetPageTemplates(Event $event)
{
$types = $event->types;
/* @var Locator $locator */
$locator = Grav::instance()['locator'];
// Set blueprints & templates.
$types->scanBlueprints($locator->findResource('plugin://events/blueprints'));
$types->scanTemplates($locator->findResource('plugin://events/templates'));
// reverse the FUBARd order of blueprints
$event = array_reverse($types['event']);
$types['event'] = $event;
}
/**
* Set needed variables to display events
*
* For the calendar page, we load the appropriate js and css to make the
* calendar work smoothly as well as add the appropriate calendar twig
* variables.
*
* @since 1.0.0 Initial Release
* @return void
*/
public function onTwigSiteVariables()
{
// setup
$page = $this->grav['page'];
$pages = $this->grav['pages'];
$collection = $pages->all()->ofType('event');
$twig = $this->grav['twig'];
$assets = $this->grav['assets'];
/** @var Uri $uri */
$uri = $this->grav['uri'];
$type = $uri->extension();
// only load the vars if calendar page
if ($page->template() == 'calendar')
{
$yearParam = $this->grav['uri']->param('year');
$monthParam = $this->grav['uri']->param('month');
$twigVars = $this->calendar->twigVars($yearParam, $monthParam);
$calVars = $this->calendar->calendarVars($collection);
// add calendar to twig as calendar
$twigVars['calendar']['events'] = $calVars;
$twig->twig_vars['calendar'] = array_shift($twigVars);
if ( $type == 'json' ) {
$twig->twig_vars['calendarJson'] = $this->calendar->calendarVars($collection);
}
}
// output on events
if ( $page->template() == 'events' && $type == 'json' ) {
$events = [];
foreach($collection as $page) {
$events[]['id'] = $page->id();
$events[]['title'] = $page->title();
$events[]['date'] = $page->date();
$events[]['header'] = $page->header();
$events[]['content'] = $page->content();
$events[]['summary'] = $page->summary();
$events[]['lang'] = $page->language();
$events[]['meta'] = $page->contentMeta();
$events[]['slug'] = $page->slug();
$events[]['permalink'] = $page->permalink();
}
$twig->twig_vars['eventsJson'] = $events;
}
$twig->twig_vars['eventCategories'] = $this->events->getEventCategories();
// scripts
$js = 'plugin://events/assets/events.min.js';
$assets->add('jquery');
$assets->addJs($js, 1);
// styles
$css = 'plugin://events/assets/events.min.css';
$assets->addCss($css);
}
/**
* Process Event Information
*
* This hook fires a reverse geocoding hook for the location field
* on single events.
*
* @param Event $event
* @since 1.0.15 Location Field Update
* @return void
*/
public function onAdminSave(Event $event)
{
$config = (array) $this->config->get('plugins.events');
// get the object being saved
$obj = $event['object'];
// check to see if the object is a `PageObject` with template `event`
if ( $obj instanceof PageObject && $obj->template() == 'event' )
{
// get the header
/** @var Header $header */
$header = $obj->header();
$event = $header->event;
// check for location information
if ( isset( $event['location'] ) && ! isset( $event['coordinates'] ) ) {
// leave if geocoding is disabled
if ( ! $config['enable_geocoding'] ) {
return;
}
$location = $event['location'];
// build a url
$url = "https://maps.googleapis.com/maps/api/geocode/json?address=" . urlencode($location) . "&key=" . $config['api_key'];
// fetch the results
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$geoloc = json_decode(curl_exec($ch), true);
foreach ( $geoloc['results'][0]['address_components'] as $address_component ) {
if($address_component['types'][0] === 'country' && $address_component['types'][1] === 'political') {
$event['country'] = $address_component['long_name'];
}
if($address_component['types'][0] === 'locality' && $address_component['types'][1] === 'political') {
$event['city'] = $address_component['long_name'];
}
if($address_component['types'][0] === 'postal_code') {
$event['zip'] = $address_component['long_name'];
}
}
// build the coord string
$lat = $geoloc['results'][0]['geometry']['location']['lat'];
$lng = $geoloc['results'][0]['geometry']['location']['lng'];
$coords = $lat . ", " . $lng;
// set the header info
$event['coordinates'] = $coords;
$header->event = $event;
$obj->header($header);
}
}
// check to see if the object is a `PageObject` with template `events`
elseif ( $obj instanceof PageObject && $obj->template() == 'events' ) {
}
else // the saved object was not a page, so it was likely the plugin settings
{
$update_mode = $event['object']["icalendar_update"];
if($update_mode != 0) {
// process iCalendar file(s)
$icalendar = new \Events\iCalendarProcessor();
$icalendar->process($update_mode-1);
// reset flag
$event['object']["icalendar_update"] = 0;
}
}
}
/**
* Association with twig extensions
*
* @since 1.1
* @return void
*/
public function onTwigExtensions()
{
require_once(__DIR__ . '/twig/DateTranslationExtension.php');
$this->grav['twig']->twig->addExtension(new DateTranslationExtension($this->grav));
}
}