PluginProbe ʕ •ᴥ•ʔ
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More / 4.0.8
Superb Addons: Blocks, Patterns, Pre-built Pages, Sliders, Popups, Free Forms, Animations & More v4.0.8
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 trunk 1.0.0 2.0.0 2.0.1 2.0.2 2.0.3 3.0 3.0.1 3.0.2 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.2 3.1.3 3.2.0 3.2.1 3.2.2 3.2.4 3.2.5 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.4.5 3.4.6 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1
superb-blocks / src / gutenberg / popup / class-popup-registry.php
superb-blocks / src / gutenberg / popup Last commit date
class-popup-button-render.php 1 week ago class-popup-registry.php 1 week ago
class-popup-registry.php
169 lines
1 <?php
2
3 namespace SuperbAddons\Gutenberg\Popup;
4
5 defined('ABSPATH') || exit();
6
7 use SuperbAddons\Data\Utils\Engagement;
8
9 class PopupRegistry
10 {
11 const OPTION_KEY = 'spb_popup_registry';
12 const BLOCK_NAME = 'superb-addons/popup';
13
14 private static $supported_post_types = array('post', 'page', 'wp_template', 'wp_template_part', 'wp_block');
15
16 /**
17 * Get the list of post types that can contain popup blocks.
18 */
19 public static function GetSupportedPostTypes()
20 {
21 return self::$supported_post_types;
22 }
23
24 public static function Initialize()
25 {
26 add_action('save_post', array(__CLASS__, 'OnSavePost'), 10, 2);
27 add_action('before_delete_post', array(__CLASS__, 'OnDeletePost'), 10, 2);
28 }
29
30 /**
31 * Hook: save_post -- scan content for popup blocks and update registry.
32 */
33 public static function OnSavePost($post_id, $post)
34 {
35 if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
36 return;
37 }
38 if (wp_is_post_revision($post_id)) {
39 return;
40 }
41 if (!in_array($post->post_type, self::$supported_post_types, true)) {
42 return;
43 }
44
45 $registry = self::GetAll();
46 $changed = false;
47
48 $found_popup_ids = array();
49 $parsed_blocks = parse_blocks($post->post_content);
50
51 foreach ($parsed_blocks as $block) {
52 self::CollectPopupBlocks($block, $found_popup_ids, $post_id, $post->post_type, $registry, $changed);
53 }
54
55 if (!empty($found_popup_ids)) {
56 Engagement::MarkUsed(Engagement::FEATURE_POPUP);
57 }
58
59 // Cleanup: remove popups that were previously on this post but are no longer
60 foreach ($registry as $pid => $data) {
61 if (isset($data['source_post_id']) && intval($data['source_post_id']) === intval($post_id) && !in_array($pid, $found_popup_ids, true)) {
62 unset($registry[$pid]);
63 $changed = true;
64 }
65 }
66
67 if ($changed) {
68 update_option(self::OPTION_KEY, $registry, false);
69 }
70 }
71
72 /**
73 * Recursively collect popup blocks and update registry entries.
74 */
75 private static function CollectPopupBlocks($block, &$found_popup_ids, $post_id, $post_type, &$registry, &$changed)
76 {
77 if (isset($block['blockName']) && $block['blockName'] === self::BLOCK_NAME && !empty($block['attrs']['popupId'])) {
78 $popup_id = self::SanitizePopupId($block['attrs']['popupId']);
79 if ($popup_id !== '') {
80 $popup_name = isset($block['attrs']['popupName']) ? sanitize_text_field($block['attrs']['popupName']) : '';
81 $found_popup_ids[] = $popup_id;
82
83 $template_slug = '';
84 if ($post_type === 'wp_template' || $post_type === 'wp_template_part') {
85 $post_obj = get_post($post_id);
86 if ($post_obj) {
87 $template_slug = $post_obj->post_name;
88 }
89 }
90
91 $entry = isset($registry[$popup_id]) ? $registry[$popup_id] : null;
92 if (
93 !$entry
94 || $entry['name'] !== $popup_name
95 || $entry['source_post_id'] !== $post_id
96 || $entry['source_post_type'] !== $post_type
97 || $entry['template_slug'] !== $template_slug
98 ) {
99 $registry[$popup_id] = array(
100 'name' => $popup_name,
101 'source_post_id' => $post_id,
102 'source_post_type' => $post_type,
103 'template_slug' => $template_slug,
104 'updated' => time(),
105 );
106 $changed = true;
107 }
108 }
109 }
110
111 // Recurse into inner blocks
112 if (!empty($block['innerBlocks'])) {
113 foreach ($block['innerBlocks'] as $inner) {
114 self::CollectPopupBlocks($inner, $found_popup_ids, $post_id, $post_type, $registry, $changed);
115 }
116 }
117 }
118
119 private static function SanitizePopupId($value)
120 {
121 if (!is_string($value)) {
122 return '';
123 }
124 return preg_replace('/[^A-Za-z0-9_-]/', '', $value);
125 }
126
127 /**
128 * Get the full registry array.
129 */
130 public static function GetAll()
131 {
132 $registry = get_option(self::OPTION_KEY, array());
133 return is_array($registry) ? $registry : array();
134 }
135
136 /**
137 * Get a single registry entry.
138 */
139 public static function Get($popup_id)
140 {
141 $registry = self::GetAll();
142 return isset($registry[$popup_id]) ? $registry[$popup_id] : null;
143 }
144
145 /**
146 * Hook: before_delete_post -- remove all registry entries for that post.
147 */
148 public static function OnDeletePost($post_id, $post)
149 {
150 if (!in_array($post->post_type, self::$supported_post_types, true)) {
151 return;
152 }
153
154 $registry = self::GetAll();
155 $changed = false;
156
157 foreach ($registry as $pid => $data) {
158 if (isset($data['source_post_id']) && intval($data['source_post_id']) === intval($post_id)) {
159 unset($registry[$pid]);
160 $changed = true;
161 }
162 }
163
164 if ($changed) {
165 update_option(self::OPTION_KEY, $registry, false);
166 }
167 }
168 }
169