389 lines
11 KiB
PHP
389 lines
11 KiB
PHP
<?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\Plugin;
|
|
use Grav\Common\Grav;
|
|
use Grav\Common\Page\Page;
|
|
use RocketTheme\Toolbox\Event\Event;
|
|
|
|
use Carbon\Carbon;
|
|
|
|
use Events\CalendarProcessor;
|
|
use Events\EventsProcessor;
|
|
|
|
/**
|
|
* 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 `Page` with template `event`
|
|
if ( $obj instanceof Page && $obj->template() == 'event' )
|
|
{
|
|
// get the header
|
|
$header = $obj->header();
|
|
|
|
// check for location information
|
|
if ( isset( $header->event['location'] ) && ! isset( $header->event['coordinates'] ) ) {
|
|
// leave if geocoding is disabled
|
|
if ( ! $config['enable_geocoding'] ) {
|
|
return;
|
|
}
|
|
|
|
$location = $header->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') {
|
|
$header->event['country'] = $address_component['long_name'];
|
|
}
|
|
|
|
if($address_component['types'][0] === 'locality' && $address_component['types'][1] === 'political') {
|
|
$header->event['city'] = $address_component['long_name'];
|
|
}
|
|
|
|
if($address_component['types'][0] === 'postal_code') {
|
|
$header->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
|
|
$header->event['coordinates'] = $coords;
|
|
$obj->header($header);
|
|
}
|
|
}
|
|
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));
|
|
}
|
|
}
|