PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.11.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.11.0
2.11.0 2.10.0 2.9.0 2.8.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 All 52 releases
thinkrank / includes / abilities / content / class-faq-ability-base.php

class-faq-ability-base.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 2.11.0, at includes/abilities/content/class-faq-ability-base.php

117 lines 3.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Shared base for the FAQ abilities.
4 *
5 * @package ThinkRank\Abilities\Content
6 */
7
8 declare(strict_types=1);
9
10 namespace ThinkRank\Abilities\Content;
11
12 use ThinkRank\Abilities\Ability_Base;
13 use ThinkRank\SEO\FAQ_Content;
14
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit; // Exit if accessed directly.
17 }
18
19 /**
20 * Post resolution and the shared FAQ item shape.
21 *
22 * A guided FAQ builder has shipped in free since 1.32.0 — the `thinkrank/faq`
23 * block plus the Elementor, Bricks and Beaver modules that mirror it, merged
24 * into one FAQPage by the schema graph. None of it was reachable through the
25 * connector, so an agent asked to add an FAQ could only write raw custom
26 * schema, which duplicates what the block already emits and marks up content
27 * that is not on the page (#767).
28 */
29 abstract class FAQ_Ability_Base extends Ability_Base {
30
31 /**
32 * Resolve a post ID to a post the current user may read.
33 *
34 * @param int $post_id Post ID.
35 * @return \WP_Post|\WP_Error
36 */
37 protected function resolve_post( int $post_id ) {
38 if ( $post_id <= 0 ) {
39 return new \WP_Error(
40 'thinkrank_invalid_post_id',
41 __( 'A valid post ID is required. Use list-content-items to find one.', 'thinkrank' ),
42 [ 'status' => 400 ]
43 );
44 }
45
46 $post = get_post( $post_id );
47
48 if ( ! $post instanceof \WP_Post ) {
49 return new \WP_Error(
50 'thinkrank_post_not_found',
51 __( 'No post was found for the provided ID.', 'thinkrank' ),
52 [ 'status' => 404 ]
53 );
54 }
55
56 return $post;
57 }
58
59 /**
60 * The shape one question is reported in, shared by both abilities.
61 *
62 * @return array<string, mixed>
63 */
64 protected function item_properties(): array {
65 return [
66 'question' => [ 'type' => 'string' ],
67 'answer' => [
68 'type' => 'string',
69 'description' => __( 'The answer as stored. May contain inline HTML, which the block renders.', 'thinkrank' ),
70 ],
71 'source' => [
72 'type' => 'string',
73 'enum' => [
74 FAQ_Content::SOURCE_BLOCK,
75 FAQ_Content::SOURCE_ELEMENTOR,
76 FAQ_Content::SOURCE_BRICKS,
77 FAQ_Content::SOURCE_BEAVER,
78 ],
79 'description' => __( 'Which editor surface holds this question. Only block items can be written by update-faq.', 'thinkrank' ),
80 ],
81 'schema_enabled' => [
82 'type' => 'boolean',
83 'description' => __( 'False when that producer has its schema toggle off, so the question is on the page but contributes nothing to FAQPage.', 'thinkrank' ),
84 ],
85 'image_id' => [ 'type' => 'integer' ],
86 'image_url' => [ 'type' => 'string' ],
87 'image_alt' => [ 'type' => 'string' ],
88 ];
89 }
90
91 /**
92 * Which builder renders this post, in the shape the schema reports.
93 *
94 * @param int $post_id Post ID.
95 * @return string One of the builder names, or 'none' for the block editor.
96 */
97 protected function builder_name( int $post_id ): string {
98 $builder = FAQ_Content::builder( $post_id );
99
100 return '' === $builder ? 'none' : $builder;
101 }
102
103 /**
104 * The builder names a post can report.
105 *
106 * @return string[]
107 */
108 protected function builder_enum(): array {
109 return [
110 'none',
111 FAQ_Content::SOURCE_ELEMENTOR,
112 FAQ_Content::SOURCE_BRICKS,
113 FAQ_Content::SOURCE_BEAVER,
114 ];
115 }
116 }
117