first draft for event reminders
Some checks failed
Some checks failed
This commit is contained in:
parent
d229529acc
commit
92fc3ecec0
16 changed files with 562 additions and 6 deletions
8
build/reminder/block.json
Normal file
8
build/reminder/block.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "reminder",
|
||||||
|
"title": "Reminder Plugin: not a block, but block.json is very useful.",
|
||||||
|
"category": "widgets",
|
||||||
|
"icon": "admin-comments",
|
||||||
|
"keywords": [],
|
||||||
|
"editorScript": "file:./plugin.js"
|
||||||
|
}
|
1
build/reminder/plugin.asset.php
Normal file
1
build/reminder/plugin.asset.php
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-components', 'wp-core-data', 'wp-data', 'wp-editor', 'wp-i18n', 'wp-plugins'), 'version' => 'f38cf2ab9e8621193407');
|
215
build/reminder/plugin.js
Normal file
215
build/reminder/plugin.js
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
/******/ (() => { // webpackBootstrap
|
||||||
|
/******/ "use strict";
|
||||||
|
/******/ var __webpack_modules__ = ({
|
||||||
|
|
||||||
|
/***/ "react/jsx-runtime":
|
||||||
|
/*!**********************************!*\
|
||||||
|
!*** external "ReactJSXRuntime" ***!
|
||||||
|
\**********************************/
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
module.exports = window["ReactJSXRuntime"];
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ "@wordpress/components":
|
||||||
|
/*!************************************!*\
|
||||||
|
!*** external ["wp","components"] ***!
|
||||||
|
\************************************/
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
module.exports = window["wp"]["components"];
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ "@wordpress/core-data":
|
||||||
|
/*!**********************************!*\
|
||||||
|
!*** external ["wp","coreData"] ***!
|
||||||
|
\**********************************/
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
module.exports = window["wp"]["coreData"];
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ "@wordpress/data":
|
||||||
|
/*!******************************!*\
|
||||||
|
!*** external ["wp","data"] ***!
|
||||||
|
\******************************/
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
module.exports = window["wp"]["data"];
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ "@wordpress/editor":
|
||||||
|
/*!********************************!*\
|
||||||
|
!*** external ["wp","editor"] ***!
|
||||||
|
\********************************/
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
module.exports = window["wp"]["editor"];
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ "@wordpress/i18n":
|
||||||
|
/*!******************************!*\
|
||||||
|
!*** external ["wp","i18n"] ***!
|
||||||
|
\******************************/
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
module.exports = window["wp"]["i18n"];
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ "@wordpress/plugins":
|
||||||
|
/*!*********************************!*\
|
||||||
|
!*** external ["wp","plugins"] ***!
|
||||||
|
\*********************************/
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
module.exports = window["wp"]["plugins"];
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
/******/ });
|
||||||
|
/************************************************************************/
|
||||||
|
/******/ // The module cache
|
||||||
|
/******/ var __webpack_module_cache__ = {};
|
||||||
|
/******/
|
||||||
|
/******/ // The require function
|
||||||
|
/******/ function __webpack_require__(moduleId) {
|
||||||
|
/******/ // Check if module is in cache
|
||||||
|
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||||
|
/******/ if (cachedModule !== undefined) {
|
||||||
|
/******/ return cachedModule.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/ // Create a new module (and put it into the cache)
|
||||||
|
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||||
|
/******/ // no module.id needed
|
||||||
|
/******/ // no module.loaded needed
|
||||||
|
/******/ exports: {}
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Execute the module function
|
||||||
|
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||||
|
/******/
|
||||||
|
/******/ // Return the exports of the module
|
||||||
|
/******/ return module.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/************************************************************************/
|
||||||
|
/******/ /* webpack/runtime/compat get default export */
|
||||||
|
/******/ (() => {
|
||||||
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||||
|
/******/ __webpack_require__.n = (module) => {
|
||||||
|
/******/ var getter = module && module.__esModule ?
|
||||||
|
/******/ () => (module['default']) :
|
||||||
|
/******/ () => (module);
|
||||||
|
/******/ __webpack_require__.d(getter, { a: getter });
|
||||||
|
/******/ return getter;
|
||||||
|
/******/ };
|
||||||
|
/******/ })();
|
||||||
|
/******/
|
||||||
|
/******/ /* webpack/runtime/define property getters */
|
||||||
|
/******/ (() => {
|
||||||
|
/******/ // define getter functions for harmony exports
|
||||||
|
/******/ __webpack_require__.d = (exports, definition) => {
|
||||||
|
/******/ for(var key in definition) {
|
||||||
|
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
||||||
|
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
||||||
|
/******/ }
|
||||||
|
/******/ }
|
||||||
|
/******/ };
|
||||||
|
/******/ })();
|
||||||
|
/******/
|
||||||
|
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
||||||
|
/******/ (() => {
|
||||||
|
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
||||||
|
/******/ })();
|
||||||
|
/******/
|
||||||
|
/******/ /* webpack/runtime/make namespace object */
|
||||||
|
/******/ (() => {
|
||||||
|
/******/ // define __esModule on exports
|
||||||
|
/******/ __webpack_require__.r = (exports) => {
|
||||||
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||||
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||||
|
/******/ }
|
||||||
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
|
/******/ };
|
||||||
|
/******/ })();
|
||||||
|
/******/
|
||||||
|
/************************************************************************/
|
||||||
|
var __webpack_exports__ = {};
|
||||||
|
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
|
||||||
|
(() => {
|
||||||
|
/*!********************************!*\
|
||||||
|
!*** ./src/reminder/plugin.js ***!
|
||||||
|
\********************************/
|
||||||
|
__webpack_require__.r(__webpack_exports__);
|
||||||
|
/* harmony import */ var _wordpress_editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/editor */ "@wordpress/editor");
|
||||||
|
/* harmony import */ var _wordpress_editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_editor__WEBPACK_IMPORTED_MODULE_0__);
|
||||||
|
/* harmony import */ var _wordpress_plugins__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/plugins */ "@wordpress/plugins");
|
||||||
|
/* harmony import */ var _wordpress_plugins__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_plugins__WEBPACK_IMPORTED_MODULE_1__);
|
||||||
|
/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
|
||||||
|
/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__);
|
||||||
|
/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/data */ "@wordpress/data");
|
||||||
|
/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_data__WEBPACK_IMPORTED_MODULE_3__);
|
||||||
|
/* harmony import */ var _wordpress_core_data__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @wordpress/core-data */ "@wordpress/core-data");
|
||||||
|
/* harmony import */ var _wordpress_core_data__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_wordpress_core_data__WEBPACK_IMPORTED_MODULE_4__);
|
||||||
|
/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
|
||||||
|
/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__);
|
||||||
|
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
|
||||||
|
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const reminderTimeGapDefault = activityPubEventBridge.reminderTypeGap;
|
||||||
|
const Reminder = () => {
|
||||||
|
const postType = (0,_wordpress_data__WEBPACK_IMPORTED_MODULE_3__.useSelect)(select => select('core/editor').getCurrentPostType(), []);
|
||||||
|
const [meta, setMeta] = (0,_wordpress_core_data__WEBPACK_IMPORTED_MODULE_4__.useEntityProp)('postType', postType, 'meta');
|
||||||
|
const reminderTimeGap = meta?.activitypub_event_bridge_reminder_time_gap ? meta?.activitypub_event_bridge_reminder_time_gap : reminderTimeGapDefault;
|
||||||
|
return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_editor__WEBPACK_IMPORTED_MODULE_0__.PluginDocumentSettingPanel, {
|
||||||
|
name: "activitypub",
|
||||||
|
title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__.__)('Send reminder before event\'s start', 'activitypub'),
|
||||||
|
children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.SelectControl, {
|
||||||
|
label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__.__)('Time gap', 'activitypub'),
|
||||||
|
value: reminderTimeGap,
|
||||||
|
options: [{
|
||||||
|
label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__.__)('Disabled', 'activitypub-event-bridge'),
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__.__)('6 hours', 'activitypub-event-bridge'),
|
||||||
|
value: 21600
|
||||||
|
}, {
|
||||||
|
label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__.__)('1 day', 'activitypub-event-bridge'),
|
||||||
|
value: 86400
|
||||||
|
}, {
|
||||||
|
label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__.__)('3 days', 'activitypub-event-bridge'),
|
||||||
|
value: 259200
|
||||||
|
}, {
|
||||||
|
label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_5__.__)('1 week', 'activitypub-event-bridge'),
|
||||||
|
value: 604800
|
||||||
|
}],
|
||||||
|
onChange: value => {
|
||||||
|
setMeta({
|
||||||
|
...meta,
|
||||||
|
activitypub_event_bridge_reminder_time_gap: value
|
||||||
|
});
|
||||||
|
},
|
||||||
|
__nextHasNoMarginBottom: true
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
(0,_wordpress_plugins__WEBPACK_IMPORTED_MODULE_1__.registerPlugin)('activitypub-event-bridge-reminder', {
|
||||||
|
render: Reminder
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******/ })()
|
||||||
|
;
|
||||||
|
//# sourceMappingURL=plugin.js.map
|
1
build/reminder/plugin.js.map
Normal file
1
build/reminder/plugin.js.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -11,6 +11,7 @@ namespace ActivityPub_Event_Bridge\Activitypub\Transformer;
|
||||||
// Exit if accessed directly.
|
// Exit if accessed directly.
|
||||||
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||||
|
|
||||||
|
use Activitypub\Activity\Activity;
|
||||||
use Activitypub\Activity\Extended_Object\Event as Event_Object;
|
use Activitypub\Activity\Extended_Object\Event as Event_Object;
|
||||||
use Activitypub\Activity\Extended_Object\Place;
|
use Activitypub\Activity\Extended_Object\Place;
|
||||||
use Activitypub\Transformer\Post;
|
use Activitypub\Transformer\Post;
|
||||||
|
@ -148,7 +149,7 @@ abstract class Event extends Post {
|
||||||
*
|
*
|
||||||
* This is mandatory and must be implemented in the final event transformer class.
|
* This is mandatory and must be implemented in the final event transformer class.
|
||||||
*/
|
*/
|
||||||
abstract protected function get_start_time(): string;
|
abstract public function get_start_time(): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the end time.
|
* Get the end time.
|
||||||
|
@ -376,4 +377,19 @@ abstract class Event extends Post {
|
||||||
|
|
||||||
return $activitypub_object;
|
return $activitypub_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an activity for announcing itself.
|
||||||
|
*
|
||||||
|
* @return Activity The Activity.
|
||||||
|
*/
|
||||||
|
public function to_announce_self_activity() {
|
||||||
|
$activity = new Activity();
|
||||||
|
$activity->set_type( 'Announce' );
|
||||||
|
|
||||||
|
// Pre-fill the Activity with data (for example cc and to).
|
||||||
|
$activity->set_object( $this->get_id() );
|
||||||
|
|
||||||
|
return $activity;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ final class GatherPress extends Event {
|
||||||
/**
|
/**
|
||||||
* Get the end time from the event object.
|
* Get the end time from the event object.
|
||||||
*/
|
*/
|
||||||
protected function get_start_time(): string {
|
public function get_start_time(): string {
|
||||||
return $this->gp_event->get_datetime_start( 'Y-m-d\TH:i:s\Z' );
|
return $this->gp_event->get_datetime_start( 'Y-m-d\TH:i:s\Z' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ final class The_Events_Calendar extends Event {
|
||||||
/**
|
/**
|
||||||
* Get the end time from the event object.
|
* Get the end time from the event object.
|
||||||
*/
|
*/
|
||||||
protected function get_start_time(): string {
|
public function get_start_time(): string {
|
||||||
$date = date_create( $this->tribe_event->start_date, wp_timezone() );
|
$date = date_create( $this->tribe_event->start_date, wp_timezone() );
|
||||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $date->getTimestamp() );
|
return \gmdate( 'Y-m-d\TH:i:s\Z', $date->getTimestamp() );
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ final class VS_Event_List extends Event_Transformer {
|
||||||
/**
|
/**
|
||||||
* Get the end time from the events metadata.
|
* Get the end time from the events metadata.
|
||||||
*/
|
*/
|
||||||
protected function get_start_time(): string {
|
public function get_start_time(): string {
|
||||||
$start_time = get_post_meta( $this->wp_object->ID, 'event-start-date', true );
|
$start_time = get_post_meta( $this->wp_object->ID, 'event-start-date', true );
|
||||||
return \gmdate( 'Y-m-d\TH:i:s\Z', $start_time );
|
return \gmdate( 'Y-m-d\TH:i:s\Z', $start_time );
|
||||||
}
|
}
|
||||||
|
|
176
includes/class-reminder.php
Normal file
176
includes/class-reminder.php
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* General settings class.
|
||||||
|
*
|
||||||
|
* This file contains the General class definition, which handles the "General" settings
|
||||||
|
* page for the ActivityPub Event Extension Plugin, providing options for configuring various general settings.
|
||||||
|
*
|
||||||
|
* @package ActivityPub_Event_Bridge
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace ActivityPub_Event_Bridge;
|
||||||
|
|
||||||
|
// Exit if accessed directly.
|
||||||
|
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||||
|
|
||||||
|
use Activitypub\Activity_Dispatcher;
|
||||||
|
use Activitypub\Transformer\Factory as Transformer_Factory;
|
||||||
|
use ActivityPub_Event_Bridge\Setup;
|
||||||
|
use ActivityPub_Event_Bridge\Activitypub\Transformer\Event as Event_Transformer;
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
|
use function Activitypub\is_user_disabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds automatic announcing or sending of reminders before the events start time.
|
||||||
|
*/
|
||||||
|
class Reminder {
|
||||||
|
/**
|
||||||
|
* Initialize the class, registering WordPress hooks.
|
||||||
|
*/
|
||||||
|
public static function init() {
|
||||||
|
// Post transitions.
|
||||||
|
\add_action( 'transition_post_status', array( self::class, 'maybe_schedule_event_post_announcement' ), 33, 3 );
|
||||||
|
|
||||||
|
// Send an event reminder.
|
||||||
|
\add_action( 'activitypub_event_bridge_send_event_reminder', array( self::class, 'send_event_reminder' ), 10, 1 );
|
||||||
|
|
||||||
|
\add_action( 'enqueue_block_editor_assets', array( self::class, 'enqueue_editor_assets' ) );
|
||||||
|
\add_action( 'init', array( self::class, 'register_postmeta' ), 11 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register post meta for controlling whether and when a reminder is scheduled for an individual event.
|
||||||
|
*/
|
||||||
|
public static function register_postmeta() {
|
||||||
|
$ap_post_types = \get_post_types_by_support( 'activitypub' );
|
||||||
|
foreach ( $ap_post_types as $post_type ) {
|
||||||
|
\register_post_meta(
|
||||||
|
$post_type,
|
||||||
|
'activitypub_event_bridge_reminder_time_gap',
|
||||||
|
array(
|
||||||
|
'show_in_rest' => true,
|
||||||
|
'single' => true,
|
||||||
|
'type' => 'integer',
|
||||||
|
'sanitize_callback' => 'absint',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue the block editor assets.
|
||||||
|
*/
|
||||||
|
public static function enqueue_editor_assets() {
|
||||||
|
// Check for our supported post types.
|
||||||
|
$current_screen = \get_current_screen();
|
||||||
|
$event_post_types = Setup::get_instance()->get_active_event_plugins_post_types();
|
||||||
|
if ( ! $current_screen || ! in_array( $current_screen->post_type, $event_post_types, true ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$asset_data = include ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_DIR . 'build/reminder/plugin.asset.php';
|
||||||
|
$plugin_url = plugins_url( 'build/reminder/plugin.js', ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_FILE );
|
||||||
|
wp_enqueue_script( 'activitypub-event-bridge-reminder', $plugin_url, $asset_data['dependencies'], $asset_data['version'], true );
|
||||||
|
|
||||||
|
// Pass the the default site wide time gap option to the settings block on the events edit page.
|
||||||
|
wp_localize_script(
|
||||||
|
'activitypub-event-bridge-reminder',
|
||||||
|
'activityPubEventBridge',
|
||||||
|
array(
|
||||||
|
'reminderTypeGap' => \get_option( 'activitypub_event_bridge_reminder_time_gap', 0 ),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule Activities.
|
||||||
|
*
|
||||||
|
* @param string $new_status New post status.
|
||||||
|
* @param string $old_status Old post status.
|
||||||
|
* @param WP_Post $post Post object.
|
||||||
|
*/
|
||||||
|
public static function maybe_schedule_event_post_announcement( $new_status, $old_status, $post ): void {
|
||||||
|
$reminder_time_gap = (int) get_post_meta( $post->ID, 'activitypub_event_bridge_reminder_time_gap', true );
|
||||||
|
|
||||||
|
if ( '' === $reminder_time_gap ) {
|
||||||
|
$reminder_time_gap = \get_option( 'activitypub_event_bridge_reminder_time_gap', 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 0 === $reminder_time_gap || ! is_int( $reminder_time_gap ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$post = get_post( $post );
|
||||||
|
|
||||||
|
if ( ! $post ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not send activities if post is password protected.
|
||||||
|
if ( \post_password_required( $post ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only schedule an reminder for event post types.
|
||||||
|
if ( ! Setup::get_instance()->is_post_type_event_of_active_event_plugin( $post->post_type ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not schedule a reminder if the event is not published.
|
||||||
|
if ( 'publish' !== $new_status ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get start time of the event.
|
||||||
|
$event_transformer = Transformer_Factory::get_transformer( $post );
|
||||||
|
|
||||||
|
if ( \is_wp_error( $event_transformer ) || ! $event_transformer instanceof Event_Transformer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$start_time = $event_transformer->get_start_time();
|
||||||
|
$start_datetime = new DateTime( $start_time );
|
||||||
|
$start_timestamp = $start_datetime->getTimestamp();
|
||||||
|
|
||||||
|
// Get the time when the reminder of the event's start should be sent.
|
||||||
|
$schedule_time = $start_timestamp - $reminder_time_gap;
|
||||||
|
|
||||||
|
if ( $schedule_time < \time() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hook = 'activitypub_event_bridge_send_event_reminder';
|
||||||
|
$args = array( $post->ID );
|
||||||
|
|
||||||
|
\wp_clear_scheduled_hook( $hook, $args );
|
||||||
|
\wp_schedule_single_event( $schedule_time, $hook, $args );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a reminder for an event post.
|
||||||
|
*
|
||||||
|
* This currently sends an Announce activity.
|
||||||
|
*
|
||||||
|
* @param int $post_id The WordPress post ID of the event post.
|
||||||
|
*/
|
||||||
|
public static function send_event_reminder( $post_id ): void {
|
||||||
|
$post = \get_post( $post_id );
|
||||||
|
|
||||||
|
$transformer = Transformer_Factory::get_transformer( $post );
|
||||||
|
|
||||||
|
if ( \is_wp_error( $transformer ) || ! $transformer instanceof Event_Transformer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_id = $transformer->get_wp_user_id();
|
||||||
|
|
||||||
|
if ( is_user_disabled( $user_id ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$activity = $transformer->to_announce_self_activity( 'Announce' );
|
||||||
|
|
||||||
|
Activity_Dispatcher::send_activity_to_followers( $activity, $user_id, $post );
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,7 +44,7 @@ class Settings {
|
||||||
'activitypub_event_bridge_default_event_category',
|
'activitypub_event_bridge_default_event_category',
|
||||||
array(
|
array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'description' => \__( 'Define your own custom post template', 'activitypub' ),
|
'description' => \__( 'Default standardized federated event category.s', 'activitypub' ),
|
||||||
'show_in_rest' => true,
|
'show_in_rest' => true,
|
||||||
'default' => self::DEFAULT_EVENT_CATEGORY,
|
'default' => self::DEFAULT_EVENT_CATEGORY,
|
||||||
'sanitize_callback' => array( self::class, 'sanitize_mapped_event_category' ),
|
'sanitize_callback' => array( self::class, 'sanitize_mapped_event_category' ),
|
||||||
|
@ -56,11 +56,22 @@ class Settings {
|
||||||
'activitypub_event_bridge_event_category_mappings',
|
'activitypub_event_bridge_event_category_mappings',
|
||||||
array(
|
array(
|
||||||
'type' => 'array',
|
'type' => 'array',
|
||||||
'description' => \__( 'Define your own custom post template', 'activitypub' ),
|
'description' => \__( 'Category mappings to standardized federated event categories.', 'activitypub' ),
|
||||||
'default' => array(),
|
'default' => array(),
|
||||||
'sanitize_callback' => array( self::class, 'sanitize_event_category_mappings' ),
|
'sanitize_callback' => array( self::class, 'sanitize_event_category_mappings' ),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
\register_setting(
|
||||||
|
'activitypub-event-bridge',
|
||||||
|
'activitypub_event_bridge_reminder_time_gap',
|
||||||
|
array(
|
||||||
|
'type' => 'array',
|
||||||
|
'description' => \__( 'Time gap in seconds when a reminder is triggered that the event is about to start.', 'activitypub' ),
|
||||||
|
'default' => array(),
|
||||||
|
'sanitize_callback' => 'absint',
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@ defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore
|
||||||
use ActivityPub_Event_Bridge\Admin\Event_Plugin_Admin_Notices;
|
use ActivityPub_Event_Bridge\Admin\Event_Plugin_Admin_Notices;
|
||||||
use ActivityPub_Event_Bridge\Admin\General_Admin_Notices;
|
use ActivityPub_Event_Bridge\Admin\General_Admin_Notices;
|
||||||
use ActivityPub_Event_Bridge\Admin\Settings_Page;
|
use ActivityPub_Event_Bridge\Admin\Settings_Page;
|
||||||
|
use ActivityPub_Event_Bridge\Reminder;
|
||||||
use ActivityPub_Event_Bridge\Plugins\Event_Plugin;
|
use ActivityPub_Event_Bridge\Plugins\Event_Plugin;
|
||||||
|
|
||||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||||
|
@ -118,6 +119,38 @@ class Setup {
|
||||||
return $this->active_event_plugins;
|
return $this->active_event_plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter function for the active event plugins post types.
|
||||||
|
*
|
||||||
|
* @return array List of event post types of the active event plugins.
|
||||||
|
*/
|
||||||
|
public function get_active_event_plugins_post_types() {
|
||||||
|
$post_types = array();
|
||||||
|
foreach ( $this->active_event_plugins as $event_plugin ) {
|
||||||
|
$post_types[] = $event_plugin->get_post_type();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $post_types;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to check whether a post type is an event post type of an active event plugin.
|
||||||
|
*
|
||||||
|
* @param string $post_type The post type.
|
||||||
|
*
|
||||||
|
* @return bool True if it is an event post type.
|
||||||
|
*/
|
||||||
|
public function is_post_type_event_of_active_event_plugin( $post_type ) {
|
||||||
|
foreach ( $this->active_event_plugins as $event_plugin ) {
|
||||||
|
if ( $post_type === $event_plugin->get_post_type() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds all the classes for the supported event plugins.
|
* Holds all the classes for the supported event plugins.
|
||||||
*
|
*
|
||||||
|
@ -185,6 +218,8 @@ class Setup {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_action( 'init', array( Reminder::class, 'init' ) );
|
||||||
|
|
||||||
add_filter( 'activitypub_transformer', array( $this, 'register_activitypub_event_transformer' ), 10, 3 );
|
add_filter( 'activitypub_transformer', array( $this, 'register_activitypub_event_transformer' ), 10, 3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ abstract class Event_Plugin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Activitypub transformer for the event plugins event post type.
|
* Returns the Activitypub transformer for the event plugins event post type.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function get_activitypub_event_transformer_class(): string {
|
public static function get_activitypub_event_transformer_class(): string {
|
||||||
return str_replace( 'Plugins', 'Activitypub\Transformer', static::class );
|
return str_replace( 'Plugins', 'Activitypub\Transformer', static::class );
|
||||||
|
|
19
package.json
Executable file
19
package.json
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "activitypub-poll",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"author": {
|
||||||
|
"name": "André Menrath",
|
||||||
|
"web": "https://graz.social/@linos"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "wp-scripts start",
|
||||||
|
"build": "wp-scripts build",
|
||||||
|
"readme": "grunt wp_readme_to_markdown"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@wordpress/scripts": "^30.0.2",
|
||||||
|
"grunt-wp-readme-to-markdown": "^2.0.1",
|
||||||
|
"classnames": "^2.3.2"
|
||||||
|
}
|
||||||
|
}
|
9
src/reminder/block.json
Normal file
9
src/reminder/block.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"name": "reminder",
|
||||||
|
"title": "Reminder Plugin: not a block, but block.json is very useful.",
|
||||||
|
"category": "widgets",
|
||||||
|
"icon": "admin-comments",
|
||||||
|
"keywords": [
|
||||||
|
],
|
||||||
|
"editorScript": "file:./plugin.js"
|
||||||
|
}
|
43
src/reminder/plugin.js
Normal file
43
src/reminder/plugin.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { PluginDocumentSettingPanel } from '@wordpress/editor';
|
||||||
|
import { registerPlugin } from '@wordpress/plugins';
|
||||||
|
import { SelectControl } from '@wordpress/components';
|
||||||
|
import { useSelect } from '@wordpress/data';
|
||||||
|
import { useEntityProp } from '@wordpress/core-data';
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
|
||||||
|
const reminderTimeGapDefault = activityPubEventBridge.reminderTypeGap;
|
||||||
|
|
||||||
|
const Reminder = () => {
|
||||||
|
const postType = useSelect(
|
||||||
|
( select ) => select( 'core/editor' ).getCurrentPostType(),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
const [ meta, setMeta ] = useEntityProp( 'postType', postType, 'meta' );
|
||||||
|
|
||||||
|
const reminderTimeGap = meta?.activitypub_event_bridge_reminder_time_gap ? meta?.activitypub_event_bridge_reminder_time_gap : reminderTimeGapDefault;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PluginDocumentSettingPanel
|
||||||
|
name="activitypub"
|
||||||
|
title={ __( 'Send reminder before event\'s start', 'activitypub' ) }
|
||||||
|
>
|
||||||
|
<SelectControl
|
||||||
|
label={ __( 'Time gap', 'activitypub' ) }
|
||||||
|
value={ reminderTimeGap }
|
||||||
|
options={ [
|
||||||
|
{ label: __( 'Disabled', 'activitypub-event-bridge' ), value: 0 },
|
||||||
|
{ label: __( '6 hours', 'activitypub-event-bridge' ), value: 21600 },
|
||||||
|
{ label: __( '1 day', 'activitypub-event-bridge' ), value: 86400 },
|
||||||
|
{ label: __( '3 days', 'activitypub-event-bridge' ), value: 259200 },
|
||||||
|
{ label: __( '1 week', 'activitypub-event-bridge' ), value: 604800 }
|
||||||
|
] }
|
||||||
|
onChange={ ( value ) => {
|
||||||
|
setMeta( { ...meta, activitypub_event_bridge_reminder_time_gap: value } );
|
||||||
|
} }
|
||||||
|
__nextHasNoMarginBottom
|
||||||
|
/>
|
||||||
|
</PluginDocumentSettingPanel>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerPlugin( 'activitypub-event-bridge-reminder', { render: Reminder } );
|
|
@ -29,6 +29,15 @@ require_once ACTIVITYPUB_EVENT_BRIDGE_PLUGIN_DIR . '/includes/event-categories.p
|
||||||
|
|
||||||
$selected_default_event_category = \get_option( 'activitypub_event_bridge_default_event_category', 'MEETING' );
|
$selected_default_event_category = \get_option( 'activitypub_event_bridge_default_event_category', 'MEETING' );
|
||||||
$current_category_mapping = \get_option( 'activitypub_event_bridge_event_category_mappings', array() );
|
$current_category_mapping = \get_option( 'activitypub_event_bridge_event_category_mappings', array() );
|
||||||
|
$reminder_time_gap = \get_option( 'activitypub_event_bridge_reminder_time_gap', 0 );
|
||||||
|
|
||||||
|
$reminder_time_gap_choices = array(
|
||||||
|
0 => __( 'Disabled', 'activitypub-event-bridge' ),
|
||||||
|
21600 => __( '6 hours', 'activitypub-event-bridge' ),
|
||||||
|
86400 => __( '1 day', 'activitypub-event-bridge' ),
|
||||||
|
259200 => __( '3 days', 'activitypub-event-bridge' ),
|
||||||
|
604800 => __( '1 week', 'activitypub-event-bridge' ),
|
||||||
|
)
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="activitypub-settings-header">
|
<div class="activitypub-settings-header">
|
||||||
|
@ -98,6 +107,17 @@ $current_category_mapping = \get_option( 'activitypub_event_bridge_event_
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<div class="box">
|
||||||
|
<h2> <?php esc_html_e( 'Send reminder before event', 'activitypub-event-bridge' ); ?> </h2>
|
||||||
|
<p> <?php esc_html_e( 'Specify a time interval before the event starts to trigger a reminder. This reminder automatically boosts the event, making it reappear in users\' timelines at the defined time before the event to increase visibility just before the event begins.', 'activitypub-event-bridge' ); ?> </p>
|
||||||
|
<select id="activitypub_event_bridge_reminder_time_gap" name="activitypub_event_bridge_reminder_time_gap">';
|
||||||
|
<?php
|
||||||
|
foreach ( $reminder_time_gap_choices as $value => $label ) {
|
||||||
|
echo '<option value="' . esc_attr( $value ) . '" ' . selected( $reminder_time_gap, $value, false ) . '>' . esc_html( $label ) . '</option>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<?php \submit_button(); ?>
|
<?php \submit_button(); ?>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue