=== OXP Events Calendar ===
Contributors: oxymaster
Tags: events, calendar, event calendar, shortcode, recurring events
Requires at least: 6.3
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Event calendar for WordPress with recurring events, categories, venues and organizers. Build a calendar visually, place it with a shortcode.

== Description ==

OXP Events Calendar adds an Events post type to WordPress and a visual composer to put it on a page. You build the calendar once, watch it render live at full width while you work, and copy out a shortcode.

Recurring events are stored once and expanded when a month is rendered, so a weekly meetup running for five years is one row in your database, not 260.

The free plan is a working calendar rather than a demo: two calendars, sixty events and six event categories, with everything below included. Venues and organizers are never counted.

**Events**

* Title, WYSIWYG description, excerpt and featured image
* Start and end date and time, all-day switch, multi-day spans
* Colour-coded categories, reusable venues with a full address, and organizers
* Event URL with its own link text and new-tab option
* Status: scheduled, cancelled, postponed, moved online or new date. The reason you type stands in for the excerpt, and one button clones a postponed event onto its new date
* Recurrence: daily, weekly on chosen weekdays, monthly by date or by weekday position, and yearly, ending on a date or after N occurrences, with dates to skip

**Calendars**

Three choices drive the output, and the preview updates as you make them.

* **Mode.** *Calendar* is the classic month grid, *Agenda* lists events grouped by day. Weekends can be shown, dimmed or dropped for a five-day week.
* **Theme.** Minimal editorial, Soft cards, Compact, or Unstyled, in a light or dark scheme. Unstyled loads no plugin CSS at all and hands you the base stylesheet ready to paste into Appearance → Customize → Additional CSS, already scoped to that one calendar.
* **Content.** Which categories, venues or organizers the calendar draws from, which filters appear, what the details popup shows, and what a click on an event does.

Colour comes from the event categories: set it once and every calendar follows.

**Front end**

* Month navigation and filtering over AJAX, with a real link and a real form underneath so it works with JavaScript off
* Filters by month, year, category and keyword, plus an optional Calendar / Agenda switch for visitors
* Accessible details modal, or a link straight to the event page or the event URL
* Every element carries an `.oxpec-` class, and day cells also carry `--today`, `--past` and `--future`

**Import and export** (Premium)

JSON in and out, from the Events list. An export is self-contained: events, recurrence rules, terms, featured image URLs, and the full definition of every category, venue and organizer it references. Terms are matched by slug and reused, and an event already there with the same slug and start is skipped, so re-importing never doubles your calendar.

**Integrations**

* `.ics` download per event and a feed for a whole calendar
* Add to Google Calendar links
* schema.org `Event` structured data for rich results
* Secure Custom Fields / ACF bridge, so `get_field()` and field bindings resolve without a second editing UI

== Free and Premium ==

Everything described above is in the free plugin. Three things are counted, and one feature is reserved:

* **Calendars: 2.** A saved calendar is a look plus a selection of events. One calendar covers several pages on its own, because every shortcode attribute overrides the saved settings for that placement.
* **Events: 60.** A recurring series counts as the single event it is stored as, whatever number of dates it produces on the page.
* **Event categories: 6**, the fallback category included. Venues and organizers have no limit, and a calendar can be narrowed by either of them.
* **JSON import and export** is part of Premium.

Nothing is counted while you stay under the limits, and nothing is deleted or hidden if a site already sits above them: the counts only decide whether one more can be created. Events, Categories and Settings each show where the site stands, and Events, Upgrade lists what a licence adds.

Premium is not on sale yet.

== External services ==

This plugin connects to Google Fonts, and to nothing else. No data about your visitors is ever sent anywhere.

**Google Fonts (fonts.googleapis.com and fonts.gstatic.com)**

What it is and what it is used for: Google Fonts is Google's font hosting service. The calendar composer offers a short list of Google font families for the calendar's typography. When you pick one, the plugin downloads that font from Google **once, to your own server**, and serves it from your uploads directory from then on. This is done so that your visitors' browsers never contact Google: the font is self-hosted, which is what keeps a calendar built with a custom font compatible with the GDPR.

What is sent and when: a request is made only in wp-admin, and only when an administrator saves a calendar that uses a Google font or previews one in the composer. The request asks `https://fonts.googleapis.com/css2` for the stylesheet of the family, weight and style you chose, and then asks `https://fonts.gstatic.com` for the `.woff2` files that stylesheet points to. What Google receives is therefore the name of the font you picked, your server's IP address, and the user agent of the request, which for the font files is WordPress's own user agent string and includes your site address. No personal data, no visitor data, no content of your site and no site identifier of ours is sent. Nothing is requested again once the font is on disk, and no request is ever made while a page is being rendered for a visitor.

If you do not choose a Google font, the plugin never contacts Google at all.

Service provided by Google: [terms of service](https://policies.google.com/terms), [privacy policy](https://policies.google.com/privacy), [Google Fonts privacy FAQ](https://developers.google.com/fonts/faq/privacy).

**Importing events**

The JSON import is not a third party service, but it does make your site fetch remote files: an export records the URL of each event's featured image, so importing a file downloads those images into your media library. The requests go to whatever site the file was exported from, which is normally your own, and they only happen when you deliberately import a file.

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/`.
2. Activate it through the Plugins screen.
3. Go to **Events → Add New Calendar**, set it up, save, and copy the shortcode.

== Where a calendar can be inserted from ==

**Settings → Implementation** lists every place the plugin can put a calendar. A builder integration only becomes selectable once that builder is detected on the site, and unchecking one removes it from that editor without touching pages that already use it.

* **Shortcode**, always on, works anywhere WordPress renders content.
* **Gutenberg block**, listed as "Events Calendar" in the inserter. It either shows one of your saved calendars or holds its own settings for that one placement: display mode, theme, colour scheme, categories, density, hiding finished events, the filter bar, and what a click does. The two are exclusive, so a block pointing at a saved calendar always follows it.
* **Elementor, Oxygen Builder, Divi, Beaver Builder and Bricks**, announced and in development, listed with their detection state so a site running one of them can see it is coming.

== Shortcode ==

`[oxpec_calendar id="12"]`

Every attribute below overrides the saved calendar for that one placement:

* `mode`: `calendar` or `agenda`
* `scheme`: `light` or `dark`
* `theme`: `minimal`, `cards`, `compact` or `custom` (`raw` is the same thing, and keeps working)
* `color`: force one hex colour on every event, in place of its category colour
* `text_color`: force a hex colour on titles and body text
* `categories`, `venues`, `organizers`: comma-separated IDs or slugs
* `link`: `modal`, `single` or `url`
* `weekends`: `show`, `hide` or `dim`
* `filters`, `ajax`, `legend`, `hide_past`: `1` or `0`
* `per_page`, `max_per_day`: numbers
* `month`, `year`: the period to open on

Example: `[oxpec_calendar id="12" mode="agenda" theme="compact" categories="concerts,talks" filters="0"]`

The earlier `view` (`grid` and `list`), `design` and `hide_weekends` attributes are still accepted and mapped to the ones that replaced them, so a shortcode never stops rendering because an attribute was renamed.

== Support ==

Write to support@oxypage.com. The **Support** and **Suggestions** links on the Plugins screen and at the top of **Events → Settings** open a mail with the subject already filled in and the plugin version included, which is the first thing any reply would otherwise have had to ask for.

== Frequently Asked Questions ==

= How do I style the calendar myself? =

In **Appearance → Customize → Additional CSS**, or in your theme, the same place as the rest of your site CSS. The plugin does not store or run a stylesheet of its own. What it does is give you everything you need to write one quickly.

Pick the **Unstyled** theme and the calendar loads no plugin CSS at all, so nothing of ours is in the way of what you write. The panel then hands you two things:

* **This calendar's class**, `.oxpec--cal-12`, which no other calendar has. Put it in front of a rule to reach one calendar, leave it off to restyle every calendar on the site.
* **The base stylesheet**, which is the **Minimal editorial** theme lifted out of `public/css/calendar.css` at runtime and trimmed to the display mode you chose, so it cannot drift from the theme it came from. Every rule arrives already limited to that calendar and can be pasted into Additional CSS as it stands.

A **Selector guide** button lists every selector the calendar puts on the page, marked with the ones that are calendar-only or agenda-only, plus a **Variables** section covering the custom properties: the accent, the category colour, and a palette that follows the light or dark scheme so one stylesheet covers both.

Everything is namespaced under `.oxpec-`, and day cells carry `--today`, `--past` and `--future`. The root carries `oxpec--mode-*`, `oxpec--theme-*` and `oxpec--scheme-*`, so you can target a single combination. If all you want is to adjust the bundled themes, override the custom properties on `.oxpec`: `--oxpec-primary`, `--oxpec-ink`, `--oxpec-line`, `--oxpec-radius` and the rest are documented at the top of `public/css/calendar.css`.

= What does the free version leave out? =

The counts, and one tool. Two calendars, sixty events and six event categories, and JSON import and export is reserved for Premium. Every other feature listed on this page is in the free plugin, including recurrence, the four themes, the visual composer, the block, the `.ics` files and the structured data. A site already holding more than a limit keeps everything it has; the limit only applies to creating one more.

= Does it slow down my site? =

The CSS and JS load only where a calendar is detected (Settings → Load plugin files → Smart). Switch to "Everywhere" only if a template renders the shortcode in a way the detector cannot see.

= What happens to my data if I delete the plugin? =

Nothing, unless you turned on **Clean uninstall** in the settings. Deactivating never touches your content. With clean uninstall on, deleting the plugin removes every event, calendar, category, venue, organizer, setting and transient.

= Can I override the single event template? =

Yes. Copy `templates/single-event.php` to `your-theme/oxp-events-calendar/single-event.php`. The plugin template is opt-in and is skipped on block themes, where the theme owns the layout.

= Does it work with my page builder? =

The shortcode works anywhere, builders included. Native integrations for Elementor, Oxygen Builder, Divi, Beaver Builder and Bricks are in development, and Settings → Implementation shows which of them the plugin has detected on your site.

== Hooks ==

Filters:

* `oxpec_event_post_type_args`: event post type registration arguments
* `oxpec_occurrences`: the resolved occurrences for a window
* `oxpec_event_query_args`: the `WP_Query` arguments used to collect events
* `oxpec_calendar_html`: the complete calendar markup
* `oxpec_event_html`: the markup of a single occurrence
* `oxpec_single_details_html`: the details block on the event page
* `oxpec_schema_event`: the JSON-LD node
* `oxpec_category_color`: the colour resolved for a category
* `oxpec_enable_scf_bridge`: whether to register the SCF / ACF field group

== Upgrade Notice ==

= 1.0.0 =
First release.

== Changelog ==

= 1.0.0 =
* First release.
* Events post type with dates and times, all-day and multi-day events, colour-coded categories, reusable venues with a full address, organizers, and an event URL with its own link text.
* Recurrence: daily, weekly on chosen weekdays, monthly by date or by weekday position, and yearly, ending on a date or after a number of occurrences, with a list of dates to skip. Series are stored once and expanded for the month being rendered.
* Event status: scheduled, cancelled, postponed, moved online or new date. Cancelled and postponed events take a reason that stands in for the excerpt, and a postponed one creates the event carrying its new date with a button, linked to the original for structured data.
* Visual calendar composer with a full-width live preview, producing a shortcode. Calendar and agenda modes, four themes in a light or dark scheme, self-hosted Google Fonts, and weekends shown, dimmed or hidden.
* Unstyled theme: no plugin CSS, with the bundled stylesheet handed over ready to paste into Additional CSS and a guide to every selector and custom property.
* Front end: month navigation and filtering over AJAX with real links and a real form underneath, an accessible details modal, and a visitor-facing calendar / agenda switch.
* Shortcode and Gutenberg block, plus a detection list for the builders still to come.
* `.ics` downloads and feeds, Add to Google Calendar links, schema.org structured data, and a Secure Custom Fields / ACF bridge.
* Free plan of two calendars, sixty events and six event categories, with JSON import and export reserved for Premium. An Upgrade screen states what a licence adds, and Settings shows where the site stands against each count.
* Spanish translation.
