PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 1.27.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v1.27.0
2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.10.0 All 48 releases
thinkrank / includes / abilities / settings / class-update-email-report-settings.php

class-update-email-report-settings.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 1.27.0, at includes/abilities/settings/class-update-email-report-settings.php

167 lines 5.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Update email report settings ability.
4 *
5 * @package ThinkRank\Abilities\Settings
6 */
7
8 declare(strict_types=1);
9
10 namespace ThinkRank\Abilities\Settings;
11
12 use ThinkRank\Abilities\Ability_Base;
13 use ThinkRank\SEO\Email_Report_Manager;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // Exit if accessed directly.
17 }
18
19 /**
20 * Updates ThinkRank Email Reporting settings.
21 *
22 * Mirrors `POST /thinkrank/v1/email-report/config`: accepts a partial config
23 * object and persists it through Email_Report_Config, which sanitizes and
24 * capability-clamps every field (Pro-only fields submitted on a free plan are
25 * silently coerced to defaults rather than rejected). Returns the persisted
26 * config and the next scheduled run.
27 */
28 class Update_Email_Report_Settings extends Ability_Base {
29 /**
30 * Constructor.
31 */
32 public function __construct() {
33 $this->id = 'thinkrank/update-email-report-settings';
34 $this->label = __( 'Update ThinkRank Email Report Settings', 'thinkrank' );
35 $this->description = __( 'Update ThinkRank Email Reporting settings: enable toggle, frequency (days), recipients, and — on plans that allow it — subject, branding, intro/footer text, enabled sections, and custom CSS. Partial updates are supported; fields not allowed on the current plan are ignored.', 'thinkrank' );
36 }
37
38 /**
39 * {@inheritDoc}
40 *
41 * @return array<string, bool|float|string>
42 */
43 public function get_annotations() {
44 return [
45 'readonly' => false,
46 'destructive' => true,
47 'idempotent' => true,
48 'priority' => 2.0,
49 'openWorldHint' => false,
50 ];
51 }
52
53 /**
54 * {@inheritDoc}
55 *
56 * @return array<string, mixed>
57 */
58 public function get_input_schema() {
59 return [
60 'type' => 'object',
61 'additionalProperties' => false,
62 'properties' => [
63 'settings' => [
64 'type' => 'object',
65 'description' => __( 'Email Reporting settings to update (any subset of the fields below).', 'thinkrank' ),
66 'additionalProperties' => false,
67 'properties' => [
68 'enabled' => [ 'type' => 'boolean' ],
69 'frequency_days' => [
70 'type' => 'integer',
71 'description' => __( 'Days between reports. Free plans are clamped to 30.', 'thinkrank' ),
72 ],
73 'recipients' => [
74 'type' => [ 'array', 'string', 'null' ],
75 'description' => __( 'Recipient email(s), as an array or comma-separated string. Free plans are clamped to the site admin email.', 'thinkrank' ),
76 ],
77 'subject_template' => [ 'type' => [ 'string', 'null' ] ],
78 'logo_url' => [ 'type' => [ 'string', 'null' ] ],
79 'logo_link' => [ 'type' => [ 'string', 'null' ] ],
80 'header_background' => [ 'type' => [ 'string', 'null' ] ],
81 'link_to_full_report' => [ 'type' => 'boolean' ],
82 'intro_text' => [ 'type' => [ 'string', 'null' ] ],
83 'sections_enabled' => [ 'type' => [ 'array', 'null' ] ],
84 'footer_text' => [ 'type' => [ 'string', 'null' ] ],
85 'additional_css' => [ 'type' => [ 'string', 'null' ] ],
86 ],
87 ],
88 ],
89 'required' => [ 'settings' ],
90 ];
91 }
92
93 /**
94 * {@inheritDoc}
95 *
96 * @return array<string, mixed>
97 */
98 public function get_output_schema() {
99 return [
100 'type' => 'object',
101 'properties' => [
102 'success' => [ 'type' => 'boolean' ],
103 'message' => [ 'type' => 'string' ],
104 'config' => [
105 'type' => 'object',
106 'description' => __( 'The persisted config after sanitization and capability-clamping.', 'thinkrank' ),
107 'additionalProperties' => true,
108 ],
109 'next_run' => [ 'type' => [ 'string', 'null' ] ],
110 ],
111 ];
112 }
113
114 /**
115 * Execute ability.
116 *
117 * @param array<string, mixed> $input Ability input payload.
118 * @return array<string, mixed>|\WP_Error
119 */
120 public function execute( $input ) {
121 $settings = isset( $input['settings'] ) && is_array( $input['settings'] ) ? $input['settings'] : [];
122
123 if ( empty( $settings ) ) {
124 return new \WP_Error(
125 'thinkrank_missing_email_report_settings_payload',
126 __( 'An email report settings payload is required.', 'thinkrank' ),
127 [ 'status' => 400 ]
128 );
129 }
130
131 $manager = $this->resolve_manager();
132
133 if ( ! $manager instanceof Email_Report_Manager ) {
134 return new \WP_Error(
135 'thinkrank_email_report_unavailable',
136 __( 'Email Report Manager is unavailable.', 'thinkrank' ),
137 [ 'status' => 500 ]
138 );
139 }
140
141 // Email_Report_Config::save() sanitizes and capability-clamps every field.
142 $saved = $manager->config()->save( $settings );
143
144 return [
145 'success' => true,
146 'message' => __( 'Email report settings updated.', 'thinkrank' ),
147 'config' => $saved,
148 'next_run' => $manager->scheduler()->next_run_iso(),
149 ];
150 }
151
152 /**
153 * Resolve the shared Email_Report_Manager from the plugin container.
154 *
155 * @return Email_Report_Manager|null
156 */
157 private function resolve_manager() {
158 if ( ! function_exists( 'thinkrank' ) ) {
159 return null;
160 }
161
162 $component = thinkrank()->get_component( 'email_report' );
163
164 return $component instanceof Email_Report_Manager ? $component : null;
165 }
166 }
167