Skip to content

Commit 1ed11fc

Browse files
committed
Add headless mode selector snippet
1 parent b04f8ea commit 1ed11fc

File tree

2 files changed

+212
-0
lines changed

2 files changed

+212
-0
lines changed

access/tsf-headless-role-selector.php

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<?php
2+
/**
3+
* Plugin Name: The SEO Framework - Set admin display level (Headless Mode)
4+
* Plugin URI: https://theseoframework.com/
5+
* Description: Allows you to set TSF's admin display capability using Headless Mode.
6+
* Version: 1.0.0
7+
* Author: Sybre Waaijer
8+
* Author URI: https://theseoframework.com/
9+
* License: GPLv3
10+
* Requires at least: 5.9
11+
* Requires PHP: 7.4.0
12+
* Requires Plugins: autodescription
13+
*
14+
* @package My_The_SEO_Framework\AdminDisplayLevel
15+
*/
16+
17+
namespace My_The_SEO_Framework\AdminDisplayLevel;
18+
19+
\defined( 'ABSPATH' ) or die;
20+
21+
/**
22+
* The display level option name.
23+
*
24+
* @since 1.0.0
25+
*/
26+
const OPTION = 'my-tsf-display-level-option';
27+
28+
/**
29+
* The options edit capability.
30+
*
31+
* @since 1.0.0
32+
*/
33+
const OPTION_CAPABILITY = 'manage_options';
34+
35+
/**
36+
* The admin page hook.
37+
*
38+
* @since 1.0.0
39+
*/
40+
const PAGE_HOOK = 'my-tsf-display-level-selector';
41+
42+
/**
43+
* The save action name.
44+
*
45+
* @since 1.0.0
46+
*/
47+
const SAVE_ACTION = 'my_tsf_display_level_settings';
48+
49+
/**
50+
* The saved action response name.
51+
*
52+
* @since 1.0.0
53+
*/
54+
const SAVED_RESPONSE = 'my_tsf_display_level_updated';
55+
56+
/**
57+
* The save nonce name and action.
58+
*
59+
* @since 1.0.0
60+
*/
61+
const SAVE_NONCE = [
62+
'name' => '_my_tsf_display_level_nonce',
63+
'action' => '_my_tsf_display_level_nonce_save_settings',
64+
];
65+
66+
\add_action( 'plugins_loaded', __NAMESPACE__ . '\set_admin_headless', 0 );
67+
\add_action( 'admin_menu', __NAMESPACE__ . '\add_menu_link', 9001 );
68+
\add_action( 'admin_post_' . SAVE_ACTION, __NAMESPACE__ . '\process_settings_submission' );
69+
70+
/**
71+
* Sets headless in admin mode.
72+
*
73+
* @hook plugins_loaded 0
74+
* @since 1.0.0
75+
*/
76+
function set_admin_headless() {
77+
78+
if ( ! \is_admin() ) return;
79+
80+
$option = \get_option( OPTION );
81+
82+
// If the option isn't set, or the user has the capability, do not define headless mode.
83+
if ( empty( $option ) || \current_user_can( $option ) ) return;
84+
85+
\defined( 'THE_SEO_FRAMEWORK_HEADLESS' )
86+
or \define( 'THE_SEO_FRAMEWORK_HEADLESS', true );
87+
}
88+
89+
/**
90+
* Adds the menu link.
91+
*
92+
* @hook admin_menu 9001
93+
* @since 1.0.0
94+
*/
95+
function add_menu_link() {
96+
\add_submenu_page(
97+
\tsf()->admin()->menu()->get_top_menu_args()['menu_slug'],
98+
'Display Level',
99+
'Display Level',
100+
OPTION_CAPABILITY,
101+
PAGE_HOOK,
102+
__NAMESPACE__ . '\display_admin_page',
103+
);
104+
}
105+
106+
/**
107+
* Processes the settings submission.
108+
*
109+
* @hook admin_post_my_tsf_display_level_settings 10
110+
* @since 1.0.0
111+
*/
112+
function process_settings_submission() {
113+
114+
\check_admin_referer( SAVE_NONCE['action'], SAVE_NONCE['name'] );
115+
116+
if ( ! \current_user_can( OPTION_CAPABILITY ) )
117+
\wp_die(
118+
\esc_html__( 'Sorry, you are not allowed to manage options for this site.', 'default' ),
119+
403,
120+
);
121+
122+
// Filter all non-true values in POST, get all keys, and then comma-separate them.
123+
$new_setting = $_POST[ OPTION ] ?? '';
124+
125+
$result = \get_option( OPTION, $new_setting ) !== $new_setting
126+
? (int) \update_option( OPTION, $new_setting )
127+
: 2;
128+
129+
\wp_safe_redirect( \add_query_arg( SAVED_RESPONSE, $result, \wp_get_referer() ) );
130+
exit;
131+
}
132+
133+
/**
134+
* Outputs the administrative page.
135+
*
136+
* @hook seo_page_my-tsf-display-level-selector 10
137+
* @since 1.0.0
138+
*/
139+
function display_admin_page() {
140+
?>
141+
<div class=wrap>
142+
<h1>Set admin display capability via Headless Mode</h1>
143+
<hr class=wp-header-end>
144+
<?php
145+
switch ( (int) ( $_GET[ SAVED_RESPONSE ] ?? -1 ) ) {
146+
case 0:
147+
?>
148+
<div id=message class="notice notice-error is-dismissible inline"><p>
149+
Settings failed to save.
150+
</p></div>
151+
<?php
152+
break;
153+
case 1:
154+
?>
155+
<div id=message class="notice notice-success is-dismissible inline"><p>
156+
Settings saved.
157+
</p></div>
158+
<?php
159+
break;
160+
case 2:
161+
?>
162+
<div id=message class="notice notice-info is-dismissible inline"><p>
163+
No settings were changed.
164+
</p></div>
165+
<?php
166+
}
167+
?>
168+
<form method=post action="<?= \esc_url( \admin_url( 'admin-post.php' ) ) ?>">
169+
<?php \wp_nonce_field( SAVE_NONCE['action'], SAVE_NONCE['name'] ); ?>
170+
<input type=hidden name=action value="<?= \esc_attr( SAVE_ACTION ) ?>">
171+
<table class=form-table role=presentation>
172+
<tr>
173+
<th scope=row>
174+
<label for="<?= \esc_attr( OPTION ) ?>">Select Role</label>
175+
</th>
176+
<td>
177+
<select name="<?= \esc_attr( OPTION ) ?>" id="<?= \esc_attr( OPTION ) ?>">
178+
<?php
179+
$current_setting = \get_option( OPTION, '' );
180+
// Show only the capabilities the current user has, so they won't lock themselves out.
181+
foreach ( \wp_get_current_user()->get_role_caps() as $role => $has ) {
182+
if ( ! $has ) continue;
183+
?>
184+
<option value="<?= \esc_attr( $role ) ?>"<?php \selected( $role, $current_setting ); ?>>
185+
<?= \esc_html( $role ) ?>
186+
</option>
187+
<?php
188+
}
189+
?>
190+
</select>
191+
<p class=description>Choose a role from the dropdown to set the admin display level. Only users with this capability can interact with The SEO Framework in the admin area.</p>
192+
</td>
193+
</tr>
194+
</table>
195+
<p class=submit>
196+
<input type=submit name="<?= \esc_attr( SAVE_ACTION ) ?>" value="Save" class="button button-primary">
197+
</p>
198+
</form>
199+
</div>
200+
<?php
201+
}

schema/tsf-image-graph.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818

1919
\add_filter(
2020
'the_seo_framework_schema_graph_data', // should be 'the_seo_framework_schema_queued_graph_data' for TSF v5.0.7+ to make references work.
21+
/**
22+
* @since 1.0.0
23+
* @param array[] $graph A sequential list of graph entities.
24+
* @param array|null $args The query arguments. Accepts 'id', 'tax', 'pta', and 'uid'.
25+
* Is null when the query is autodetermined.
26+
* @return array[] The adjusted graph.
27+
*/
2128
function ( $graph, $args ) {
2229

2330
foreach ( $graph as &$data ) {
@@ -39,16 +46,19 @@ function ( $graph, $args ) {
3946
class My_Graph_Image extends \The_SEO_Framework\Meta\Schema\Entities\Reference {
4047

4148
/**
49+
* @since 1.0.0
4250
* @var string|string[] $type The Schema @type.
4351
*/
4452
public static $type = 'ImageObject';
4553

4654
/**
55+
* @since 1.0.0
4756
* @var int $image_id The current image iterated. 0 is the PrimaryImage.
4857
*/
4958
public static $image_id = 0;
5059

5160
/**
61+
* @since 1.0.0
5262
* @param array|null $args The query arguments. Accepts 'id', 'tax', 'pta', and 'uid'.
5363
* Leave null to autodetermine query.
5464
* @return string The entity ID for $args.
@@ -59,6 +69,7 @@ public static function get_id( $args = null ) { // phpcs:ignore, VariableAnalysi
5969
}
6070

6171
/**
72+
* @since 1.0.0
6273
* @param array|null $args The query arguments. Accepts 'id', 'tax', 'pta', and 'uid'.
6374
* Leave null to autodetermine query.
6475
* @return ?array $entity The Schema.org graph entity. Null on failure.

0 commit comments

Comments
 (0)