-
Notifications
You must be signed in to change notification settings - Fork 65
/
sage-acf-gutenberg-blocks.php
247 lines (212 loc) · 9.69 KB
/
sage-acf-gutenberg-blocks.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
<?php
namespace App;
// Check whether WordPress and ACF are available; bail if not.
if (! function_exists('acf_register_block_type')) {
return;
}
if (! function_exists('add_filter')) {
return;
}
if (! function_exists('add_action')) {
return;
}
// Add the default blocks location, 'views/blocks', via filter
add_filter('sage-acf-gutenberg-blocks-templates', function () {
return ['views/blocks'];
});
/**
* Create blocks based on templates found in Sage's "views/blocks" directory
*/
add_action('acf/init', function () {
// Global $sage_error so we can throw errors in the typical sage manner
global $sage_error;
// Get an array of directories containing blocks
$directories = apply_filters('sage-acf-gutenberg-blocks-templates', []);
// Check whether ACF exists before continuing
foreach ($directories as $directory) {
$dir = isSage10() ? \Roots\resource_path($directory) : \locate_template($directory);
// Sanity check whether the directory we're iterating over exists first
if (!file_exists($dir)) {
return;
}
// Iterate over the directories provided and look for templates
$template_directory = new \DirectoryIterator($dir);
foreach ($template_directory as $template) {
if (!$template->isDot() && !$template->isDir()) {
// Strip the file extension to get the slug
$slug = removeBladeExtension($template->getFilename());
// If there is no slug (most likely because the filename does
// not end with ".blade.php", move on to the next file.
if (!$slug) {
continue;
}
// Get header info from the found template file(s)
$file = "$dir/$slug.blade.php";
$file_path = file_exists($file) ? $file : '';
$file_headers = get_file_data($file_path, [
'title' => 'Title',
'description' => 'Description',
'category' => 'Category',
'icon' => 'Icon',
'keywords' => 'Keywords',
'mode' => 'Mode',
'align' => 'Align',
'post_types' => 'PostTypes',
'supports_align' => 'SupportsAlign',
'supports_anchor' => 'SupportsAnchor',
'supports_mode' => 'SupportsMode',
'supports_jsx' => 'SupportsInnerBlocks',
'supports_align_text' => 'SupportsAlignText',
'supports_align_content' => 'SupportsAlignContent',
'supports_multiple' => 'SupportsMultiple',
'enqueue_style' => 'EnqueueStyle',
'enqueue_script' => 'EnqueueScript',
'enqueue_assets' => 'EnqueueAssets',
]);
if (empty($file_headers['title'])) {
$sage_error(__('This block needs a title: ' . $dir . '/' . $template->getFilename(), 'sage'), __('Block title missing', 'sage'));
}
if (empty($file_headers['category'])) {
$sage_error(__('This block needs a category: ' . $dir . '/' . $template->getFilename(), 'sage'), __('Block category missing', 'sage'));
}
// Checks if dist contains this asset, then enqueues the dist version.
if (!empty($file_headers['enqueue_style'])) {
checkAssetPath($file_headers['enqueue_style']);
}
if (!empty($file_headers['enqueue_script'])) {
checkAssetPath($file_headers['enqueue_script']);
}
// Set up block data for registration
$data = [
'name' => $slug,
'title' => $file_headers['title'],
'description' => $file_headers['description'],
'category' => $file_headers['category'],
'icon' => $file_headers['icon'],
'keywords' => explode(' ', $file_headers['keywords']),
'mode' => $file_headers['mode'],
'align' => $file_headers['align'],
'render_callback' => __NAMESPACE__.'\\sage_blocks_callback',
'enqueue_style' => $file_headers['enqueue_style'],
'enqueue_script' => $file_headers['enqueue_script'],
'enqueue_assets' => $file_headers['enqueue_assets'],
'example' => array(
'attributes' => array(
'mode' => 'preview',
)
)
];
// If the PostTypes header is set in the template, restrict this block to those types
if (!empty($file_headers['post_types'])) {
$data['post_types'] = explode(' ', $file_headers['post_types']);
}
// If the SupportsAlign header is set in the template, restrict this block to those aligns
if (!empty($file_headers['supports_align'])) {
$data['supports']['align'] = in_array($file_headers['supports_align'], array('true', 'false'), true) ? filter_var($file_headers['supports_align'], FILTER_VALIDATE_BOOLEAN) : explode(' ', $file_headers['supports_align']);
}
// If the SupportsMode header is set in the template, restrict this block mode feature
if (!empty($file_headers['supports_anchor'])) {
$data['supports']['anchor'] = $file_headers['supports_anchor'] === 'true' ? true : false;
}
// If the SupportsMode header is set in the template, restrict this block mode feature
if (!empty($file_headers['supports_mode'])) {
$data['supports']['mode'] = $file_headers['supports_mode'] === 'true' ? true : false;
}
// If the SupportsInnerBlocks header is set in the template, restrict this block mode feature
if (!empty($file_headers['supports_jsx'])) {
$data['supports']['jsx'] = $file_headers['supports_jsx'] === 'true' ? true : false;
}
// If the SupportsAlignText header is set in the template, restrict this block mode feature
if (!empty($file_headers['supports_align_text'])) {
$data['supports']['align_text'] = $file_headers['supports_align_text'] === 'true' ? true : false;
}
// If the SupportsAlignContent header is set in the template, restrict this block mode feature
if (!empty($file_headers['supports_align_text'])) {
$data['supports']['align_content'] = $file_headers['supports_align_content'] === 'true' ? true : false;
}
// If the SupportsMultiple header is set in the template, restrict this block multiple feature
if (!empty($file_headers['supports_multiple'])) {
$data['supports']['multiple'] = $file_headers['supports_multiple'] === 'true' ? true : false;
}
// Register the block with ACF
\acf_register_block_type(apply_filters("sage/blocks/$slug/register-data", $data));
}
}
}
});
/**
* Callback to register blocks
*/
function sage_blocks_callback($block, $content = '', $is_preview = false, $post_id = 0)
{
// Set up the slug to be useful
$slug = str_replace('acf/', '', $block['name']);
$block = array_merge(['className' => ''], $block);
// Set up the block data
$block['post_id'] = $post_id;
$block['is_preview'] = $is_preview;
$block['content'] = $content;
$block['slug'] = $slug;
$block['anchor'] = isset($block['anchor']) ? $block['anchor'] : '';
// Send classes as array to filter for easy manipulation.
$block['classes'] = [
$slug,
$block['className'],
$block['is_preview'] ? 'is-preview' : null,
'align'.$block['align']
];
// Filter the block data.
$block = apply_filters("sage/blocks/$slug/data", $block);
// Join up the classes.
$block['classes'] = implode(' ', array_filter($block['classes']));
// Get the template directories.
$directories = apply_filters('sage-acf-gutenberg-blocks-templates', []);
foreach ($directories as $directory) {
$view = ltrim($directory, 'views/') . '/' . $slug;
if (isSage10()) {
if (\Roots\view()->exists($view)) {
// Use Sage's view() function to echo the block and populate it with data
echo \Roots\view($view, ['block' => $block]);
}
} else {
echo \App\template(locate_template("$directory/$slug"), ['block' => $block]);
}
}
}
/**
* Function to strip the `.blade.php` from a blade filename
*/
function removeBladeExtension($filename)
{
// Filename must end with ".blade.php". Parenthetical captures the slug.
$blade_pattern = '/(.*)\.blade\.php$/';
$matches = [];
// If the filename matches the pattern, return the slug.
if (preg_match($blade_pattern, $filename, $matches)) {
return $matches[1];
}
// Return FALSE if the filename doesn't match the pattern.
return false;
}
/**
* Checks asset path for specified asset.
*
* @param string &$path
*
* @return void
*/
function checkAssetPath(&$path)
{
if (preg_match("/^(styles|scripts)/", $path)) {
$path = isSage10() ? \Roots\asset($path)->uri() : \App\asset_path($path);
}
}
/**
* Check if Sage 10 is used.
*
* @return bool
*/
function isSage10()
{
return class_exists('Roots\Acorn\Application');
}