PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / models / FrmGatedItem.php

FrmGatedItem.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More trunk, at classes/models/FrmGatedItem.php

172 lines 4.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Gated Content Item
4 *
5 * Value object representing a single item in a gated content action's items list.
6 * Subclasses add type-specific properties and can override matches(), get_url(),
7 * and get_title() for type-specific behaviour.
8 *
9 * @package Formidable
10 *
11 * @since 6.33
12 */
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 die( 'You are not allowed to call this page directly.' );
16 }
17
18 class FrmGatedItem {
19
20 /**
21 * Item type slug (e.g. 'post', 'frm_file', 'frm_pdf').
22 *
23 * @var string
24 */
25 public $type;
26
27 /**
28 * Content item ID (page post ID, attachment ID, view ID, …).
29 *
30 * @var int|string
31 */
32 public $id;
33
34 /**
35 * @param array{type: string, id: int|string} $item Item data array with 'type' and 'id' keys.
36 */
37 public function __construct( array $item ) {
38 $this->type = $item['type'];
39 $this->id = $item['id'];
40 }
41
42 /**
43 * Create a FrmGatedItem (or subclass) for the given type and ID.
44 *
45 * Fires `frm_gated_item_make` so Pro and add-on plugins can return a
46 * subclass instance for their own item types without Lite needing to know
47 * about them.
48 *
49 * @param array{type: string, id: int|string} $item Item data array with 'type' and 'id' keys.
50 *
51 * @return FrmGatedItem
52 */
53 public static function make( array $item ) {
54 /**
55 * Create a subclass instance for a non-core item type.
56 *
57 * Return a FrmGatedItem subclass instance to handle the given type.
58 * Return null to fall back to the base FrmGatedItem.
59 *
60 * @since 6.33
61 *
62 * @param FrmGatedItem|null $instance Instance, or null to use base class.
63 * @param array{type: string, id: int|string} $item Item data array with 'type' and 'id' keys.
64 */
65 $instance = apply_filters( 'frm_gated_item_make', null, $item );
66
67 return $instance instanceof self ? $instance : new self( $item );
68 }
69
70 /**
71 * Check whether this item matches a raw item settings array.
72 *
73 * Subclasses may override to implement type-specific matching logic.
74 *
75 * @param array $item_data Raw item array from action settings (must have 'type' and 'id' keys).
76 *
77 * @return bool
78 */
79 public function matches( $item_data ) {
80 return is_array( $item_data )
81 && isset( $item_data['type'], $item_data['id'] )
82 && $item_data['type'] === $this->type
83 && (string) $item_data['id'] === (string) $this->id;
84 }
85
86 /**
87 * Return the gated access URL for this item.
88 *
89 * Base implementation handles 'post' items (permalink + access_code). Subclasses
90 * override this for type-specific URL schemes.
91 *
92 * @param string $raw_token Raw access token to append as the access_code query arg.
93 *
94 * @return string Full URL with access_code parameter, or empty string on failure.
95 */
96 public function get_url( $raw_token ) {
97 $url = self::get_permalink_for_gated_item( $this->id );
98 return $url ? add_query_arg( 'access_code', $raw_token, $url ) : '';
99 }
100
101 /**
102 * Return the permalink for a gated item, using the pretty URL even for private posts/pages.
103 *
104 * WordPress's _get_page_link() falls back to ?page_id=ID for private pages when
105 * the current user cannot read private pages. Passing a cloned post object with
106 * post_status set to 'publish' bypasses that capability check.
107 *
108 * @param int $post_id Post ID.
109 *
110 * @return string
111 */
112 protected static function get_permalink_for_gated_item( $post_id ) {
113 /**
114 * @var WP_Post|null $post
115 */
116 $post = get_post( $post_id );
117
118 if ( ! $post instanceof WP_Post ) {
119 return '';
120 }
121
122 if ( 'private' === $post->post_status ) {
123 $post = clone $post;
124 $post->post_status = 'publish';
125 }
126
127 return get_permalink( $post );
128 }
129
130 /**
131 * Return the display title for this item.
132 *
133 * Base implementation handles 'post' items (post title). Subclasses override
134 * this for type-specific titles.
135 *
136 * @return string Display title, or empty string when unavailable.
137 */
138 public function get_title() {
139 return get_the_title( $this->id );
140 }
141
142 /**
143 * Return the cookie name used to persist the access token for this item.
144 *
145 * Subclasses may override to produce a more specific name — e.g. when the
146 * same post type can have multiple distinct access scopes (view + entry).
147 *
148 * @since 6.33
149 *
150 * @return string
151 */
152 public function get_cookie_name() {
153 return 'frm_gc_' . $this->get_transient_key();
154 }
155
156 /**
157 * Return the item-specific segment used to build cache/transient keys.
158 *
159 * Callers prepend their own prefix and any additional scope identifiers
160 * (e.g. action ID) to form the full key. Subclasses may override to
161 * include extra scope — e.g. entry ID for view items — so that cache
162 * entries for different access scopes never collide.
163 *
164 * @since 6.33
165 *
166 * @return string
167 */
168 public function get_transient_key() {
169 return $this->type . '_' . $this->id;
170 }
171 }
172