PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.3.0
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.3.0
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 All 66 releases
better-payment / includes / AI / Schema / ElementContentGuide.php

ElementContentGuide.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.3.0, at includes/AI/Schema/ElementContentGuide.php

111 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Better_Payment\Lite\AI\Schema;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 /**
10 * Per-widget content direction handed to the model alongside the element schema.
11 *
12 * The schema tells the model which *keys* an element accepts. It says nothing
13 * about what belongs *in* them, and a bare key list is not self-describing: a
14 * `headline` on `progress_bar` is a one-line status ("Nearly there"), a
15 * `headline` on `campaign_description` is a section heading, and a `headline` on
16 * `social_sharing` is a call to share. Given only the word "headline" three
17 * times, a model writes the same sentence three times — which is exactly how
18 * generated campaigns ended up reading as one undifferentiated blob of copy
19 * with the campaign title restated in four places.
20 *
21 * So each element type gets a short directive describing what its content is
22 * *for*. This is prompt text, not validation — {@see OperationValidator} remains
23 * the boundary that decides what is actually allowed through.
24 *
25 * Two of these guides are load-bearing rather than stylistic, and must not be
26 * softened into generic writing advice:
27 *
28 * - **`social_links` must never invent a URL.** A plausible-looking
29 * `facebook.com/<something>` is not a harmless placeholder; it is a link from
30 * a fundraising page to an account the campaign does not control, and it may
31 * well belong to a real unrelated person.
32 * - **`donors_wall` must never contain donor names.** It renders live
33 * transaction data. A model writing example donors into it would be
34 * fabricating a record of who gave money — the same reason Lite's
35 * {@see \Better_Payment\Lite\Campaign\Elements\ProElementPreview} keeps its
36 * sample donors obviously fictional and builder-only.
37 *
38 * Keyed by element type, so an element with no entry simply gets no guidance
39 * line (third-party elements registered via `better_payment/campaign_elements`
40 * are described by their schema alone).
41 *
42 * @see PromptBuilder::describe_schema() Renders these under each element.
43 * @see CampaignSchema::for_prompt() Attaches them to the schema payload.
44 */
45 class ElementContentGuide {
46
47 /**
48 * Element type => one-paragraph content directive.
49 *
50 * Kept to a couple of sentences each: this ships on every request, and a
51 * guide long enough to crowd out the user's own brief defeats the purpose.
52 *
53 * @return array<string, string>
54 */
55 private static function guides(): array {
56 $guides = [
57 'campaign_title' => __( 'A 4–10 word headline naming who or what the money helps and why it is urgent. Specific, not a category ("Get Amara Back on Her Feet", never "Medical Fundraiser"). No trailing period, no organisation name on its own, and never the same wording you use anywhere else on the page.', 'better-payment' ),
58
59 'campaign_description' => __( 'The story, and the only long-form copy on the page: 2–4 short paragraphs in `content`. Open on the person or situation, give concrete verifiable detail (what happened, what the money buys, what changes if it is funded), and close on what a donation does. Use `headline` only as a section heading for the story ("Amara\'s Story") — never a restatement of the campaign title.', 'better-payment' ),
60
61 'photo' => __( 'Write `alt` only, and write it as a real description of the scene the image shows for a reader who cannot see it. Never set `src` — the system supplies the actual image and any URL you invent is a broken link.', 'better-payment' ),
62
63 'progress_bar' => __( 'A live figure widget: it renders the real raised/goal numbers itself. `headline` is an optional one-line status in words, not numbers ("Nearly there" / "Every donation moves this bar"). `goal_label` and `donate_label` are short prefixes the renderer appends the amount to — write "Our goal:" and stop.', 'better-payment' ),
64
65 'campaign_summary' => __( 'A compact live stats block (raised, donors, percent, days left) — the numbers come from the campaign, never from you. `headline` names the block in 2–4 words ("Where we stand"). Turn off any stat the campaign cannot support: `show_days` on a campaign with no end date shows nothing useful.', 'better-payment' ),
66
67 'donation_form' => __( 'The primary call to action. `button_label` is an imperative of 2–4 words, specific to the cause where it can be ("Fund Amara\'s Surgery", "Give Shelter Tonight") rather than a bare "Submit". An amount inside the button text is fine here — unlike a `*_label` key, this one is echoed on its own.', 'better-payment' ),
68
69 'organizer' => __( 'Who is behind the campaign, for trust. `role_title` is the role or relationship ("Amara\'s sister", "Shelter Director"), never a personal name — the name comes from the linked WordPress user. `description` is 1–2 sentences of credibility in the organiser\'s own first-person voice.', 'better-payment' ),
70
71 'donate_amount' => __( 'The giving tiers. `headline` invites a choice in a few words ("Choose your impact"). The tiers themselves go in the separate `set_donation_amounts` operation, where each amount\'s description states what that specific sum concretely does ("Feeds one family for a week") — an impact, never a restatement of the number.', 'better-payment' ),
72
73 'social_sharing' => __( 'Share buttons for this page. `headline` is a short ask ("Share Amara\'s story"). The network toggles only decide which buttons appear — the links are generated from the campaign URL, so there is nothing for you to write into them.', 'better-payment' ),
74
75 'social_links' => __( 'Links to the organiser\'s OWN existing profiles. Set a network\'s URL ONLY if the brief gives you that exact address; otherwise leave every URL unset and let the element stay empty. Never construct a plausible handle — an invented profile link points a fundraising page at an account nobody involved controls.', 'better-payment' ),
76
77 // --- Pro elements. Described only when Pro is active; see CampaignSchema::offerable_elements().
78 'donors_wall' => __( 'A live list of real donors, rendered from actual transactions — you write no donor names, amounts or dates, and there is no setting to put them in. Your job is `headline` ("Thank you to our supporters") and the display options: `layout`, how many to show, and which columns are visible.', 'better-payment' ),
79
80 'faq' => __( 'Answers to what a hesitant donor of THIS campaign would actually ask before giving. Write 3–5 items in `items`, each a real question in the donor\'s voice with a direct 1–3 sentence answer — how the money is used, what happens if the goal is not met, whether the payment is secure, when the help arrives. Never generic filler, and never a question the page already answers.', 'better-payment' ),
81
82 'video' => __( 'An embedded campaign video. Set `url` ONLY if the brief contains the actual video address; a video ID you invent resolves to an unrelated stranger\'s video on the fundraising page. With no URL in the brief, leave `url` out entirely and set only the display options.', 'better-payment' ),
83 ];
84
85 /**
86 * Filter the per-element content guidance sent to the model.
87 *
88 * @param array<string, string> $guides Element type => directive.
89 */
90 return apply_filters( 'better_payment/ai/element_content_guides', $guides );
91 }
92
93 /**
94 * The directive for one element type, or '' when it has none.
95 */
96 public static function for_type( string $type ): string {
97 $guides = self::guides();
98
99 return isset( $guides[ $type ] ) ? (string) $guides[ $type ] : '';
100 }
101
102 /**
103 * Every element type that carries a directive.
104 *
105 * @return array<int, string>
106 */
107 public static function types(): array {
108 return array_keys( self::guides() );
109 }
110 }
111