PluginProbe
Content Blocks Builder – Create blocks, repeater blocks with carousel, grid, popup layouts / trunk
Content Blocks Builder – Create blocks, repeater blocks with carousel, grid, popup layouts vtrunk
2.8.14 2.8.13 2.8.12 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.8.0 2.8.1 2.8.10 2.8.11 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 trunk 1.0.1 1.0.2 1.1.0 1.1.1 All 147 releases
content-blocks-builder / src / custom-blocks / missing-blocks.js

missing-blocks.js in Content Blocks Builder – Create blocks, repeater blocks with carousel, grid, popup layouts trunk, at src/custom-blocks/missing-blocks.js

264 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * External dependencies
3 */
4 import { map, isObject, isArray, isUndefined, isEmpty } from "lodash";
5
6 /**
7 * WordPress dependencies
8 */
9 import { __, sprintf } from "@wordpress/i18n";
10 import { useSelect, useDispatch } from "@wordpress/data";
11 import { registerPlugin } from "@wordpress/plugins";
12 import { useEffect, useMemo } from "@wordpress/element";
13 import {
14 getBlockTypes,
15 unregisterBlockType,
16 unregisterBlockVariation,
17 } from "@wordpress/blocks";
18 import { store as noticesStore } from "@wordpress/notices";
19
20 /**
21 * Internal dependencies
22 */
23 import { log } from "sdk/utils";
24 import {
25 getDependentBlockTypes,
26 getVariationDependentBlockTypes,
27 hasMissingBlocks,
28 getEditPostURL,
29 getNoticeActions,
30 userCanManagePlugins,
31 } from "../utils";
32 import { store as boldblocksDataStore } from "../store";
33 import { shareLabels } from "../utils/shared-labels";
34
35 /**
36 * Disable blocks if they have missing blocks
37 */
38 registerPlugin("boldblocks-disable-blocks-with-missing-blocks", {
39 render: () => {
40 const { createWarningNotice } = useDispatch(noticesStore);
41 const { getMissingBlockStatus } = useSelect(
42 (select) => select(boldblocksDataStore),
43 [],
44 );
45 const { loadMissingBlock, setMissingBlockStatus } =
46 useDispatch(boldblocksDataStore);
47 const canManagePlugins = userCanManagePlugins();
48
49 const missingBlocks = useMemo(() => {
50 const availableBlockTypes = getBlockTypes();
51 const availableBlockNames = map(availableBlockTypes, "name");
52
53 return (CBBBlocks?.blocks ?? []).reduce(
54 (prev, { id, name, title, blocks: rawBlocks, dependentBlocks }) => {
55 if (!isArray(dependentBlocks) || !dependentBlocks.length) {
56 let blocks;
57 try {
58 blocks = JSON.parse(rawBlocks);
59 } catch (error) {
60 log(error, "error");
61 }
62
63 if (blocks && isArray(blocks)) {
64 dependentBlocks = getDependentBlockTypes(blocks, []);
65 }
66 }
67
68 if (isArray(dependentBlocks) && !!dependentBlocks.length) {
69 const missingBlock = hasMissingBlocks(
70 dependentBlocks,
71 availableBlockNames,
72 );
73 if (missingBlock) {
74 prev.push({
75 id,
76 name,
77 title,
78 missingBlock,
79 });
80 }
81 }
82
83 return prev;
84 },
85 [],
86 );
87 }, []);
88
89 useEffect(() => {
90 if (!!missingBlocks.length) {
91 missingBlocks.forEach((block) => {
92 const { name } = block;
93 unregisterBlockType(name);
94 });
95 }
96 }, []);
97
98 useEffect(() => {
99 // The variable has been loaded and has some missing blocks
100 if (!isUndefined(canManagePlugins) && !!missingBlocks.length) {
101 missingBlocks.forEach(async (block) => {
102 const { id, name, missingBlock } = block;
103 const noticeId = `block-${id}`;
104 if (!getMissingBlockStatus(noticeId)) {
105 let actions = [
106 {
107 label: sprintf(shareLabels.editItem, shareLabels.block),
108 url: getEditPostURL(id),
109 },
110 ];
111 const filterValue = `block:${missingBlock}`;
112
113 const noticeMessage = sprintf(
114 __(
115 "The block %s has been disabled because it contains a missing block %s.",
116 "content-blocks-builder",
117 ),
118 name,
119 missingBlock,
120 );
121
122 log(noticeMessage, "warn");
123
124 let plugin;
125 try {
126 plugin = await loadMissingBlock(filterValue);
127 } catch (error) {
128 log(error, "error");
129 }
130
131 if (plugin && !isEmpty(plugin)) {
132 actions.push(...getNoticeActions(plugin));
133 }
134
135 createWarningNotice(noticeMessage, { actions });
136 setMissingBlockStatus(noticeId);
137 }
138 });
139 }
140 }, [canManagePlugins, missingBlocks.length]);
141
142 return null;
143 },
144 });
145
146 /**
147 * Disable variations if they have missing blocks
148 */
149 registerPlugin("boldblocks-disable-variations-with-missing-blocks", {
150 render: () => {
151 const { createWarningNotice } = useDispatch(noticesStore);
152 const { getMissingBlockStatus } = useSelect(
153 (select) => select(boldblocksDataStore),
154 [],
155 );
156 const { loadMissingBlock, setMissingBlockStatus } =
157 useDispatch(boldblocksDataStore);
158 const canManagePlugins = userCanManagePlugins();
159
160 const missingVariations = useMemo(() => {
161 const availableBlockTypes = getBlockTypes();
162 const availableBlockNames = map(availableBlockTypes, "name");
163
164 return (CBBBlocks?.variations ?? []).reduce(
165 (
166 prev,
167 { id, blockName, variationName, variationData, dependentBlocks },
168 ) => {
169 if (!isArray(dependentBlocks) || !dependentBlocks.length) {
170 let variation;
171 try {
172 ({ variation } = JSON.parse(variationData));
173 } catch (error) {
174 log(error, "error");
175 }
176
177 if (variation && isObject(variation)) {
178 const { innerBlocks = [] } = variation;
179 dependentBlocks = getVariationDependentBlockTypes(
180 innerBlocks,
181 [],
182 );
183 }
184 }
185
186 if (isArray(dependentBlocks) && !!dependentBlocks.length) {
187 const missingBlock = hasMissingBlocks(
188 dependentBlocks,
189 availableBlockNames,
190 );
191 if (missingBlock) {
192 prev.push({
193 id,
194 variationName,
195 blockName,
196 missingBlock,
197 });
198 }
199 }
200
201 return prev;
202 },
203 [],
204 );
205 }, []);
206
207 useEffect(() => {
208 if (!!missingVariations.length) {
209 missingVariations.forEach((variation) => {
210 const { blockName, variationName } = variation;
211 unregisterBlockVariation(blockName, variationName);
212 });
213 }
214 }, []);
215
216 useEffect(() => {
217 if (!isUndefined(canManagePlugins) && !!missingVariations.length) {
218 missingVariations.forEach(async (variation) => {
219 const { id, missingBlock, variationName: name } = variation;
220
221 const noticeId = `variation-${id}`;
222 if (!getMissingBlockStatus(noticeId)) {
223 let actions = [
224 {
225 label: sprintf(shareLabels.editItem, shareLabels.variation),
226 url: getEditPostURL(id),
227 },
228 ];
229
230 const noticeMessage = sprintf(
231 __(
232 "The variation %s has been disabled because it contains a missing block %s.",
233 "content-blocks-builder",
234 ),
235 name,
236 missingBlock,
237 );
238
239 log(noticeMessage, "warn");
240
241 const filterValue = `block:${missingBlock}`;
242
243 let plugin;
244 try {
245 plugin = await loadMissingBlock(filterValue);
246 } catch (error) {
247 log(error, "error");
248 }
249
250 if (plugin && !isEmpty(plugin)) {
251 actions.push(...getNoticeActions(plugin));
252 }
253
254 createWarningNotice(noticeMessage, { actions });
255 setMissingBlockStatus(noticeId);
256 }
257 });
258 }
259 }, [canManagePlugins, missingVariations.length]);
260
261 return null;
262 },
263 });
264