Basic settings page with configurables
This commit is contained in:
parent
1cd9fa3c29
commit
ff5a382856
6 changed files with 351 additions and 2 deletions
94
.forgejo/workflows/package.yml
Normal file
94
.forgejo/workflows/package.yml
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
# Building and releasing Wordpress plugins is pretty simple
|
||||||
|
# It's just zipping up some PHP. This doesn't contain any unit tests
|
||||||
|
# this is just zipping and shipping.
|
||||||
|
#
|
||||||
|
# Generally speaking your directory structure would be:
|
||||||
|
# .
|
||||||
|
# ├── README.md
|
||||||
|
# └── src
|
||||||
|
# └── wordpress-plugin.php
|
||||||
|
#
|
||||||
|
# With the repository name being the name of your plugin to make it easier
|
||||||
|
# to Google for. Up to you though; you can configure the source dir below.
|
||||||
|
#
|
||||||
|
# When you tag a commit and the tag stats with 'v', this workflow will
|
||||||
|
# zip and ship the Wordpress plugin to the 'releases' tab of Github or Forgejo
|
||||||
|
|
||||||
|
name: Build & Release WordPress Plugin
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: docker
|
||||||
|
container: debian:12
|
||||||
|
|
||||||
|
env:
|
||||||
|
SOURCE_DIR: "src"
|
||||||
|
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Prepare Build Environment
|
||||||
|
run: |
|
||||||
|
apt update && apt -y install zip unzip nodejs curl jq
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Package plugin
|
||||||
|
run: |
|
||||||
|
# Set plugin name like this because it's easier than inline
|
||||||
|
PLUGIN_NAME=$(echo $GITHUB_REPOSITORY | awk -F'/' '{ print $2 }')
|
||||||
|
|
||||||
|
# Create a build directory to ensure that we're correctly creating
|
||||||
|
# a single child directory in the zip.
|
||||||
|
mkdir -p build
|
||||||
|
cp -r ${SOURCE_DIR} "build/${PLUGIN_NAME}"
|
||||||
|
|
||||||
|
# Zip it up for shipping
|
||||||
|
cd build
|
||||||
|
zip -r "../${PLUGIN_NAME}.zip" "${PLUGIN_NAME}"
|
||||||
|
cd -
|
||||||
|
unzip -l "${PLUGIN_NAME}.zip"
|
||||||
|
|
||||||
|
- name: Create Release if not exists
|
||||||
|
run: |
|
||||||
|
# Curl request that uses the repos token & Forgejo's built-in variables
|
||||||
|
# to create a new release based on the tag that you have pushed
|
||||||
|
#
|
||||||
|
# It doesn't care if the release exists or not.
|
||||||
|
curl -X POST "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases" \
|
||||||
|
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"tag_name": "'"${GITHUB_REF##*/}"'",
|
||||||
|
"target_commitish": "main",
|
||||||
|
"name": "'"${GITHUB_REF##*/}"'",
|
||||||
|
"body": "Auto release",
|
||||||
|
"draft": false,
|
||||||
|
"prerelease": false
|
||||||
|
}' || true
|
||||||
|
|
||||||
|
- name: Upload Plugin Zip to Release
|
||||||
|
run: |
|
||||||
|
# Set some variables because it's cleaner than in-line
|
||||||
|
TAG_NAME="${GITHUB_REF##*/}"
|
||||||
|
REPO_NAME="$(basename $GITHUB_REPOSITORY)"
|
||||||
|
PLUGIN_NAME=$(echo $GITHUB_REPOSITORY | awk -F'/' '{ print $2 }')
|
||||||
|
|
||||||
|
# Get the release ID created in the last step
|
||||||
|
RELEASE_ID=$(curl -s \
|
||||||
|
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
|
||||||
|
"${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/tags/${TAG_NAME}" \
|
||||||
|
| jq -r '.id')
|
||||||
|
|
||||||
|
# Pushes he zip file to be shown in the "Releases" tab under this release.
|
||||||
|
curl -X POST "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets" \
|
||||||
|
-H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \
|
||||||
|
-F "name=${PLUGIN_NAME}.zip" \
|
||||||
|
-F "attachment=@${PLUGIN_NAME}.zip"
|
||||||
|
|
43
README.md
43
README.md
|
@ -1,3 +1,42 @@
|
||||||
# fwp-recaptcha
|
# fwp-calendar
|
||||||
|
|
||||||
Provides basic Google Recaptcha protections for your Wordpress blog.
|
Originally created for a customer, I imagine that this would help some people
|
||||||
|
wanting to avoid Wordpresses increasing "pay to use" direction.
|
||||||
|
|
||||||
|
Accepts a list of iCal URLs (without auth) and publishes to a page.
|
||||||
|
|
||||||
|
Almost entirely generated with ChatGPT. I lay no claim that I have manually
|
||||||
|
written this entire thing myself. I just need something working and fast.
|
||||||
|
|
||||||
|
## MVP
|
||||||
|
|
||||||
|
The MVP has very basic functionality. We leverage two external libraries however
|
||||||
|
have included them within the plugin:
|
||||||
|
|
||||||
|
1. [FullCalendar](https://github.com/fullcalendar/fullcalendar)
|
||||||
|
2. [ics-parser](https://github.com/u01jmg3/ics-parser)
|
||||||
|
|
||||||
|
We pull from a public iCal/ICS URL via the server. We then process and display
|
||||||
|
this information when a shortcode (`[event-calendar]`) is called.
|
||||||
|
|
||||||
|
We store a list/array of URLs to pull from, so you should be able to add a
|
||||||
|
couple.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Just install then look in "Settings" for the "FWP Calendar" section.
|
||||||
|
|
||||||
|
You can add a simple list of ICS/iCal URLs there however they must be publicly
|
||||||
|
accessible. I tested and it works with Google calendars.
|
||||||
|
|
||||||
|
I created this for a customer who had a list of upcoming events displayed on
|
||||||
|
their website. They were manually updating the events calendar entirely through
|
||||||
|
Wordpress, which seemed clunky.
|
||||||
|
|
||||||
|
This plugin allows you to maintain a community events calendar from within your
|
||||||
|
Orgs typical public calendar. Visitors can see events spread out on a calendar
|
||||||
|
and upcoming events below.
|
||||||
|
|
||||||
|
This is good because you can provide the calendar for people to add to their
|
||||||
|
phones or import into their own calendars. Your options are endless when you
|
||||||
|
don't use shitty proprietary standards!
|
||||||
|
|
34
docker-compose.yaml
Normal file
34
docker-compose.yaml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: wp_test_db
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: rootpassword
|
||||||
|
MYSQL_DATABASE: wordpress
|
||||||
|
MYSQL_USER: wordpress
|
||||||
|
MYSQL_PASSWORD: wordpress
|
||||||
|
volumes:
|
||||||
|
- db_data:/var/lib/mysql
|
||||||
|
|
||||||
|
wordpress:
|
||||||
|
image: wordpress:latest
|
||||||
|
container_name: wp_test_app
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
WORDPRESS_DB_HOST: db:3306
|
||||||
|
WORDPRESS_DB_USER: wordpress
|
||||||
|
WORDPRESS_DB_PASSWORD: wordpress
|
||||||
|
WORDPRESS_DB_NAME: wordpress
|
||||||
|
WORDPRESS_DEBUG: 'true'
|
||||||
|
WORDPRESS_DEBUG_LOG: 'true'
|
||||||
|
WORDPRESS_DEBUG_DISPLAY: 'false'
|
||||||
|
volumes:
|
||||||
|
- ./src:/var/www/html/wp-content/plugins/fwp-recaptcha
|
||||||
|
volumes:
|
||||||
|
db_data:
|
||||||
|
|
74
src/funcs/settings.php
Normal file
74
src/funcs/settings.php
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
defined('ABSPATH') or exit;
|
||||||
|
|
||||||
|
// === Add FWP Settings Menu + Recaptcha Page ===
|
||||||
|
add_action('admin_menu', 'fwp_add_settings_pages');
|
||||||
|
function fwp_add_settings_pages() {
|
||||||
|
// Create top-level "FWP Settings" if not already present
|
||||||
|
if (!isset($GLOBALS['admin_page_hooks']['fwp-settings'])) {
|
||||||
|
add_menu_page(
|
||||||
|
'FWP Settings',
|
||||||
|
'FWP Settings',
|
||||||
|
'manage_options',
|
||||||
|
'fwp-settings',
|
||||||
|
'__return_null',
|
||||||
|
'dashicons-admin-generic',
|
||||||
|
80
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add FWP Recaptcha submenu
|
||||||
|
add_submenu_page(
|
||||||
|
'fwp-settings',
|
||||||
|
'FWP reCAPTCHA',
|
||||||
|
'FWP reCAPTCHA',
|
||||||
|
'manage_options',
|
||||||
|
'fwp-recaptcha',
|
||||||
|
'fwp_render_recaptcha_settings_page'
|
||||||
|
);
|
||||||
|
|
||||||
|
remove_submenu_page('fwp-settings', 'fwp-settings');
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Register Settings ===
|
||||||
|
add_action('admin_init', 'fwp_register_recaptcha_settings');
|
||||||
|
function fwp_register_recaptcha_settings() {
|
||||||
|
register_setting('fwp_recaptcha_settings_group', 'fwp_recaptcha_enabled_forms');
|
||||||
|
register_setting('fwp_recaptcha_settings_group', 'fwp_recaptcha_site_key');
|
||||||
|
register_setting('fwp_recaptcha_settings_group', 'fwp_recaptcha_secret_key');
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Render Settings Page ===
|
||||||
|
function fwp_render_recaptcha_settings_page() {
|
||||||
|
$enabled = get_option('fwp_recaptcha_enabled_forms', ['login', 'register', 'comment']);
|
||||||
|
$site_key = get_option('fwp_recaptcha_site_key', '');
|
||||||
|
$secret_key = get_option('fwp_recaptcha_secret_key', '');
|
||||||
|
?>
|
||||||
|
<div class="wrap">
|
||||||
|
<h1>FWP reCAPTCHA Settings</h1>
|
||||||
|
<form method="post" action="options.php">
|
||||||
|
<?php settings_fields('fwp_recaptcha_settings_group'); ?>
|
||||||
|
<table class="form-table" role="presentation">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Enable reCAPTCHA on:</th>
|
||||||
|
<td>
|
||||||
|
<label><input type="checkbox" name="fwp_recaptcha_enabled_forms[]" value="login" <?php checked(in_array('login', $enabled)); ?>> Login Form</label><br>
|
||||||
|
<label><input type="checkbox" name="fwp_recaptcha_enabled_forms[]" value="register" <?php checked(in_array('register', $enabled)); ?>> Registration Form</label><br>
|
||||||
|
<label><input type="checkbox" name="fwp_recaptcha_enabled_forms[]" value="comment" <?php checked(in_array('comment', $enabled)); ?>> Comment Form</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><label for="fwp_recaptcha_site_key">Site Key</label></th>
|
||||||
|
<td><input type="text" name="fwp_recaptcha_site_key" id="fwp_recaptcha_site_key" value="<?php echo esc_attr($site_key); ?>" class="regular-text" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><label for="fwp_recaptcha_secret_key">Secret Key</label></th>
|
||||||
|
<td><input type="text" name="fwp_recaptcha_secret_key" id="fwp_recaptcha_secret_key" value="<?php echo esc_attr($secret_key); ?>" class="regular-text" /></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<?php submit_button(); ?>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
90
src/fwp-calendar.php
Normal file
90
src/fwp-calendar.php
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: Free WordPress Google Recaptcha
|
||||||
|
* Plugin URI: https://repobase.net/free-wordpress/fwp-recaptcha/
|
||||||
|
* Description: Protect your Wordpress forms with Googles Recaptcha.
|
||||||
|
* Version: 0.0.1
|
||||||
|
* Author: Jacob Brown
|
||||||
|
* License: GPL2
|
||||||
|
* Text Domain: fwp-recaptcha
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: Universal reCAPTCHA
|
||||||
|
* Description: Adds Google reCAPTCHA to login, register, comment, and other forms via hooks.
|
||||||
|
* Version: 1.0
|
||||||
|
* Author: OpenAI
|
||||||
|
* License: GPL2
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined('ABSPATH') or die('No script kiddies please.');
|
||||||
|
|
||||||
|
define('URC_SITE_KEY', 'your-site-key-here');
|
||||||
|
define('URC_SECRET_KEY', 'your-secret-key-here');
|
||||||
|
|
||||||
|
// Enqueue reCAPTCHA script globally
|
||||||
|
add_action('wp_enqueue_scripts', 'urc_enqueue_recaptcha');
|
||||||
|
add_action('login_enqueue_scripts', 'urc_enqueue_recaptcha');
|
||||||
|
|
||||||
|
function urc_enqueue_recaptcha() {
|
||||||
|
wp_enqueue_script('google-recaptcha', 'https://www.google.com/recaptcha/api.js', [], null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add reCAPTCHA field to login, register, and comment forms
|
||||||
|
add_action('login_form', 'urc_display_recaptcha');
|
||||||
|
add_action('register_form', 'urc_display_recaptcha');
|
||||||
|
add_action('comment_form_after_fields', 'urc_display_recaptcha');
|
||||||
|
add_action('comment_form_logged_in_after', 'urc_display_recaptcha');
|
||||||
|
|
||||||
|
function urc_display_recaptcha() {
|
||||||
|
echo '<div class="g-recaptcha" data-sitekey="' . esc_attr(URC_SITE_KEY) . '"></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate login form
|
||||||
|
add_filter('authenticate', 'urc_verify_recaptcha_on_login', 30, 3);
|
||||||
|
function urc_verify_recaptcha_on_login($user, $username, $password) {
|
||||||
|
if (!urc_is_recaptcha_valid()) {
|
||||||
|
return new WP_Error('recaptcha_invalid', __('<strong>ERROR</strong>: Please complete the reCAPTCHA.'));
|
||||||
|
}
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate registration
|
||||||
|
add_action('registration_errors', 'urc_verify_recaptcha_on_register', 10, 3);
|
||||||
|
function urc_verify_recaptcha_on_register($errors, $sanitized_user_login, $user_email) {
|
||||||
|
if (!urc_is_recaptcha_valid()) {
|
||||||
|
$errors->add('recaptcha_invalid', __('ERROR: Please complete the reCAPTCHA.'));
|
||||||
|
}
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate comment form
|
||||||
|
add_filter('preprocess_comment', 'urc_verify_recaptcha_on_comment');
|
||||||
|
function urc_verify_recaptcha_on_comment($commentdata) {
|
||||||
|
if (!urc_is_recaptcha_valid()) {
|
||||||
|
wp_die(__('ERROR: Please complete the reCAPTCHA.'));
|
||||||
|
}
|
||||||
|
return $commentdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reCAPTCHA validation helper
|
||||||
|
function urc_is_recaptcha_valid() {
|
||||||
|
if (isset($_POST['g-recaptcha-response'])) {
|
||||||
|
$response = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', [
|
||||||
|
'body' => [
|
||||||
|
'secret' => URC_SECRET_KEY,
|
||||||
|
'response' => sanitize_text_field($_POST['g-recaptcha-response']),
|
||||||
|
'remoteip' => $_SERVER['REMOTE_ADDR'],
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!is_wp_error($response)) {
|
||||||
|
$data = json_decode(wp_remote_retrieve_body($response), true);
|
||||||
|
return isset($data['success']) && $data['success'] === true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
18
src/fwp-recaptcha.php
Normal file
18
src/fwp-recaptcha.php
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: Free WordPress Google Recaptcha
|
||||||
|
* Plugin URI: https://repobase.net/free-wordpress/fwp-recaptcha/
|
||||||
|
* Description: Protect your Wordpress forms with Googles Recaptcha.
|
||||||
|
* Version: 0.0.1
|
||||||
|
* Author: Free Wordpress
|
||||||
|
* License: GPL2
|
||||||
|
* Text Domain: fwp-recaptcha
|
||||||
|
*/
|
||||||
|
|
||||||
|
defined('ABSPATH') or exit;
|
||||||
|
|
||||||
|
// Load settings and admin menu
|
||||||
|
require_once plugin_dir_path(__FILE__) . 'funcs/settings.php';
|
||||||
|
|
||||||
|
// Your future frontend logic (hook into forms) would go here
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue