PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.4.0
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.4.0
2.4.1 2.4.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 All 68 releases
better-payment / includes / Campaign / Templates / ProTemplateCatalog.php

ProTemplateCatalog.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.4.0, at includes/Campaign/Templates/ProTemplateCatalog.php

172 lines 8.1 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\Campaign\Templates;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 /**
10 * Card metadata for the four Pro-only campaign templates, so a free install can
11 * SHOW them — locked — instead of pretending they do not exist.
12 *
13 * ## Why this lives in Lite
14 *
15 * It is the same split {@see \Better_Payment\Lite\Campaign\Elements\ProElementStubs}
16 * makes for the three Pro elements: **Lite owns the description of the product,
17 * Pro owns the product.** A free install has no copy of Pro on disk, so without a
18 * catalogue here the Pro templates are simply absent from the picker and a free
19 * user has no way to learn they exist. What crosses the boundary is a card —
20 * label, one-line description, category tags, a thumbnail and an accent colour.
21 * No layout, no elements, no settings, no business logic.
22 *
23 * ## What is deliberately NOT here
24 *
25 * `columns` is always `array()`. That is the enforcement, not a shortcut: the
26 * locked entry physically cannot build a page, so even a client that ignored
27 * every UI gate and dispatched `APPLY_TEMPLATE` on one would produce an empty
28 * campaign rather than a free copy of a Pro design. The real layouts stay in
29 * `Better_Payment\Pro\Campaign\BuilderTemplates` and ship only with Pro.
30 *
31 * ## Entitlement
32 *
33 * Read live from `better_payment/pro_enabled` on every call, exactly like every
34 * other Pro gate in the builder — never inferred from stored campaign data. With
35 * Pro active {@see self::get_locked()} returns nothing at all: Pro registers the
36 * real templates under these same keys through
37 * `better_payment/campaign_templates`, and a paying customer must never be shown
38 * a lock, a crown or an upsell for something they already own. (The keys
39 * matching is not a coincidence to be tidied away — it is what makes the locked
40 * card and the real template the same product to the user, and Pro's
41 * `BuilderTemplatesRegistrationTest` fails if the two lists drift.)
42 *
43 * ## Card order
44 *
45 * The picker renders templates in registry order, so this array is a layout
46 * decision. These four are merged in after Lite's own eight and continue their
47 * 2-column → split → 1-column rotation rather than grouping by preset, and the
48 * accents are spread so no two similar hues land side by side in a three-up
49 * grid. **The same order is repeated in Pro's `BuilderTemplates` and a test
50 * asserts the two match** — otherwise a free install and a paid one would show
51 * the same twelve cards in two different arrangements.
52 *
53 * ## `theme_class` is carried here on purpose
54 *
55 * Unlike the rest of a locked card, `theme_class` is not advertising — it is
56 * what a campaign resolves on every page view. A customer who built with Pro and
57 * then let the licence lapse still has `_bpc_template_key` pointing at one of
58 * these. The design behind `bp-v2-water` and the other three ships with Pro and
59 * does not load without it, but Lite's campaign-display stylesheet keeps the four
60 * classes in its shared v2 selector list, backed by zero-specificity `:where()`
61 * fallback tokens. Carrying the class keeps that page a plain, readable v2 design
62 * instead of dropping it out of the v2 system altogether, and reactivating Pro
63 * restores the full design with no data change. It is a class name, not CSS.
64 *
65 * ## Thumbnails — the only preview a locked card has
66 *
67 * Lite ships its own copies under `assets/img/campaign/templates/preview/pro/`.
68 * Pointing at Pro's asset URL would 404 on the only install that needs these
69 * cards — the one without Pro — and a template whose thumbnail fails to load
70 * falls back to a flat `preview_color` block, which sells nothing. The Preview
71 * lightbox shows the same screenshot: Lite carries no copy of Pro's layouts, so
72 * a locked card is never rendered live. Keep the two sets of files in sync when
73 * Pro's artwork changes.
74 *
75 * @since 2.3.2
76 */
77 class ProTemplateCatalog {
78
79 /**
80 * Path below Lite's assets/ where Lite's copies of the Pro card thumbnails live.
81 */
82 const PREVIEW_DIR = 'assets/img/campaign/templates/preview/pro';
83
84 /**
85 * The locked Pro template cards, or an empty array when Pro is active.
86 *
87 * @return array<string, array> Templates keyed by template key.
88 */
89 public static function get_locked(): array {
90 if ( apply_filters( 'better_payment/pro_enabled', false ) ) {
91 return array();
92 }
93
94 return self::catalog();
95 }
96
97 /**
98 * Every Pro template card, regardless of entitlement.
99 *
100 * Entitlement-blind on purpose, so tests and the Pro-side drift check can
101 * read the list without having to fake a licence. Production code wants
102 * {@see self::get_locked()}.
103 *
104 * @return array<string, array>
105 */
106 public static function catalog(): array {
107 $templates = array(
108 'pro-emergency-relief-v2' => array(
109 'key' => 'pro-emergency-relief-v2',
110 'label' => __( 'Food Drive Campaign', 'better-payment' ),
111 'description' => __( 'Community food appeal with a live donation ticker, video and FAQ beside a sticky giving panel.', 'better-payment' ),
112 'tags' => array( 'charity' ),
113 'layout' => '2-column',
114 'theme_class' => 'bp-v2-fooddrive',
115 'preview_color' => '#f59e0b',
116 'preview_image' => self::PREVIEW_DIR . '/Food-Drive-Campaign-v2.webp',
117 ),
118 'pro-nonprofit-landing-v2' => array(
119 'key' => 'pro-nonprofit-landing-v2',
120 'label' => __( 'Climate Action Campaign', 'better-payment' ),
121 'description' => __( 'Long-form single-column landing page — hero, proof, and the ask repeated where readers reach it.', 'better-payment' ),
122 'tags' => array( 'environmental' ),
123 'layout' => '1-column',
124 'theme_class' => 'bp-v2-climate',
125 'preview_color' => '#1d4ed8',
126 'preview_image' => self::PREVIEW_DIR . '/Climate-Action-Campaign-v2.webp',
127 ),
128 'pro-modern-fundraising-v2' => array(
129 'key' => 'pro-modern-fundraising-v2',
130 'label' => __( 'Clean Water Campaign', 'better-payment' ),
131 'description' => __( 'Full-width hero, then story and donation side by side — with video, FAQ and a live donor wall.', 'better-payment' ),
132 'tags' => array( 'charity' ),
133 'layout' => 'split',
134 'theme_class' => 'bp-v2-water',
135 'preview_color' => '#0369a1',
136 'preview_image' => self::PREVIEW_DIR . '/Clean-Water-Campaign-v2.webp',
137 ),
138 'pro-community-support-v2' => array(
139 'key' => 'pro-community-support-v2',
140 'label' => __( 'Wildlife Conservation Campaign', 'better-payment' ),
141 'description' => __( 'Habitat restoration page built around a public supporters wall, with video and FAQ.', 'better-payment' ),
142 'tags' => array( 'environmental' ),
143 'layout' => '1-column',
144 'theme_class' => 'bp-v2-wildlife',
145 'preview_color' => '#4d7c0f',
146 'preview_image' => self::PREVIEW_DIR . '/Wildlife-Conservation-Campaign-v2.webp',
147 ),
148 );
149
150 // Applied here rather than repeated in each entry: `pro` is what the
151 // builder's shared lock predicate reads (utils/proEnabled.js), and
152 // `columns` being empty is the contract the whole class rests on — both
153 // are properties of "this is a catalogue entry", not of any one template.
154 foreach ( $templates as $key => $template ) {
155 $templates[ $key ]['category'] = 'prebuilt';
156 $templates[ $key ]['pro'] = true;
157 $templates[ $key ]['columns'] = array();
158 }
159
160 return $templates;
161 }
162
163 /**
164 * The four Pro template keys.
165 *
166 * @return string[]
167 */
168 public static function keys(): array {
169 return array_keys( self::catalog() );
170 }
171 }
172