I created a WordPress Plugin, with a hook to create links below the overview of posts in the backend(for a custom post type).
The link should redirect to a custom PHP-File. Which is currently solved like this (for Terminierungsverwaltung):
class CustomPlugin
{
function __construct(){
#... more code
/**
* Terminverwaltung
*/
add_filter( 'post_row_actions', array( $this,'termin_add_user_action_button'), 10, 2 );
#... more code
}
#... more code
function termin_add_user_action_button($actions, $post){
global $wpdb;
$post_id = $post->ID; //post ID
$poll_id; //poll ID
$wordpress_polls = $wpdb->get_results("SELECT wordpress_id, poll_id FROM " . self::WORDPRESS_TABLE_NAME . " WHERE wordpress_id = " . $post_id);
$wordpress_polls_rows = $wpdb->num_rows;
foreach($wordpress_polls as $wordpress_poll){
$poll_id = $wordpress_poll->poll_id;
}
if($wordpress_polls_rows === NULL || $wordpress_polls_rows === 0){
return $actions;
} else{
if(get_post_type() === 'workshop'){
$url = add_query_arg(
array(
'post_id' => $post->ID,
'poll_id' => $poll_id,
),
plugins_url( '/attendees.php', __FILE__ )
);
$actions['termin_add_user'] = '<a href="' . $url . '" target="_blank">Teilnehmerverwaltung</a>';
}
return $actions;
}
}
#... more code
}
So currently I am pointing directly to the source file attendees.php
(which is located inside the plugin directory) and it is not protected.
My aim is to protect the attendees.php
with:
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
Obviously, I will need to hook the file somehow to the plugin or WordPress, so ABSPATH is defined. But I am not sure how to do it. Does anyone know how to get this done?
I am new to PHP and WordPress, so sorry if this is a newbie question.
Thanks in advance!
THE-E
In case the attendees.php
is of importance, it has currently this structure, and should be displayed independently:
<?php
// if ( ! defined( 'ABSPATH' ) ) {
// exit; // Exit if accessed directly.
// }
require '../../../wp-load.php';
require 'src/attendees_function.php';
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel = "stylesheet"
type = "text/css"
href = "style/attendeesStyle.css" />
<title>Teilnehmerverwaltung: <?php echo get_the_title($_REQUEST['post_id']);?></title>
</head>
<body>
<?php add_user_form(); ?>
<?php delete_attendee(); ?>
<?php upload(); ?>
<H1>Teilnehmerverwaltung</H1>
<H2><?php echo get_the_title($_REQUEST['post_id']);?></H2>
<section>
<div id="add-users-upload">
<form method="POST" enctype="multipart/form-data" id="csv-form">
<input type="file" name="teilnehmer-csv" accept=".csv"><br>
<button type="submit" name="csv-upload" id="top-buttons">Teilnehmer CSV hochladen</button>
</form>
<form method="post">
<label for="kuerzel">Kürzel:</label>
<input type="hidden" name="poll-id" value="<?php $poll_id = $_REQUEST['poll_id']; echo $poll_id; ?>"/>
<input type="hidden" name="table" value="<?php $table = "oc_polls_share"; echo $table; ?>"/>
<input type="text" class="form-control" id="input-kuerzel" name="kuerzel"><br>
<button type="submit" name="add-user-form" id="top-buttons">Teilnehmer anlegen</button>
</form>
</div>
</section>
<div id="table-div">
<table>
</thead>
<tr>
<td id="index">#</td>
<td id="index">Status</td>
<td id="header">Kürzel</td>
<td id="header">E-Mail</td>
<td id="header">Vorname</td>
<td id="header">Nachname</td>
<td id="header">Geburtstag</td>
<td id="header">Token</td>
<td id="header">Löschen</td>
<td id="header">Umfrage-Link</td>
<td id="header">Webseiten-Link</td>
<td id="header">Senden</td>
</tr>
</thead>
<tbody>
<?php
$nextcloud_base_url = "https://example.com";
$nextcloud_attendees_base_url = $nextcloud_base_url . "/apps/polls/s/";
if(isset($_REQUEST['post_id']) && isset($_REQUEST['poll_id'])){
$post_id = $_REQUEST['post_id']; //post ID
$poll_id = $_REQUEST['poll_id']; //poll ID
}
$wordpress_polls_table_name = 'wordpress_polls'; //storage of primary keys of post id and poll id
$polls_share_table_name = 'oc_polls_share'; //attendees table
$wordpress_polls = get_wordpress_polls($wordpress_polls_table_name, $post_id);
$wordpress_polls_rows = get_wordpress_polls($wordpress_polls_table_name, $post_id);
$poll_id = get_poll_id($wordpress_polls);
if($wordpress_polls_rows === NULL || $wordpress_polls_rows === 0){
return;
} else {
$attendees = get_attendees($polls_share_table_name, $poll_id);
$attendees_rows = get_attendees_rows($polls_share_table_name, $poll_id);
create_attendee_rows($attendees, $nextcloud_attendees_base_url);
}
?>
</tbody>
</table>
</div>
<div id="legende">
<p>
Status-Legende:<br>
❌ = Abstimmung nicht erfolgt<br>
✅ = Abstimmung erfolgt
</p>
</div>
</body>
</html>
EDIT: I am looking into the Custom Endpoints Documentation, but couldn't get it to work for now.
Meanwhile a picture of the content I want to integrate (attendees.php)
There's a bunch of ways to solve this which I'll try to outline. These are not in order of recommendation, just stream on consciousness. I would recommend #2, if it is viable, however.
This question shows shows how to do this and this answer gives pros and cons for each, but the general idea is to require_once
either the wp-load.php
or the wp-blog-header.php
files from root, and you'd probably want the former. Doing this, however, is usually discouraged and I would only recommend it for cases where you need access to basic WordPress functions. If you do this, WordPress doesn't know what your security requirements are, so it will be up to you to perform access control using things like current_user_can
.
Although I posted this first, I would strongly recommended avoiding this, and if you are distributing your plugin, especially in the WordPress.org repo, absolutely don't do this because I'm pretty certain it would be rejected.
If you are willing so sacrifice some pixel space (for the admin toolbars), this is the recommended way. Just register a menu using add_menu_page
and you can either echo
or include
/require
your code:
add_action(
'admin_menu',
static function () {
add_menu_page(
'My Plugin',
'My Plugin',
'manage_options',
'my-plugin',
static function () {
// Either echo here or use an include/require
echo '<h1>Hello world</h1>';
}
);
}
);
The URL to this page is based on the fourth parameter to that function, which using the above would be /wp-admin/admin.php?page=my-plugin
. Access control is handled automatically with the third parameter which makes certain that the user has the manage_options
permission. You can customize that as needed, and optionally create your own permissions, too.
The template_include
function is used to determine which front-end WordPress template to use. Personally, I don't like using this for admin stuff because I like to keep things separate from each other, but that's just me. In this code sample below I'm setting a template in the theme's folder, but it could just as easily be in the plugin's folder.
add_filter(
'template_include',
static function ($template) {
// Pick whatever logic you want here, it could be `_GET` or `_POST` or pretty much anything
if ('my-plugin' === ($_GET['action'] ?? null)) {
$template = get_template_directory() . '/searchform.php';
}
return $template;
}
);
The if
logic is where you do whatever you want. I'm just showing a simple _GET
check where the URL would be /?action=my-plugin
. Security, once again, is up to you, but you have full access to WordPress core functions like current_user_can
to do whatever is necessary.
This is actually a version of #3 because you are just making the URL prettier. I personally think it is over-complicated because it is a multi-step process with a lot of moving parts, but if the URL is important to you it might work. Make sure to flush your permalinks! The key to this is rewrite_rules_array
where you register a custom regex for the URL and you can provide whatever logic you need, including querystrings and whatever.
// Register a global variable for the URL so that WordPress is aware that you care about it
add_filter(
'query_vars',
static function ($vars) {
$vars[] = 'my-plugin';
return $vars;
}
);
// Add special regex-like syntax for URLs. You can go wild here, too
add_action(
'rewrite_rules_array',
static function ($rules) {
$newrules = array();
// The true isn't important, it could be anything. The my-plugin is what
// matters. Make sure to flush your permalinks!
$newrules['my-plugin/?$'] = 'index.php?my-plugin=true';
return $newrules + $rules;
}
);
add_action(
'template_include',
static function ($template) {
if (get_query_var('my-plugin')) {
$template = get_template_directory() . '/searchform.php';
}
return $template;
}
);