PluginProbe ʕ •ᴥ•ʔ
VikAppointments Services Booking Calendar / trunk
VikAppointments Services Booking Calendar vtrunk
trunk 1.2.17 1.2.18 1.2.19
vikappointments / libraries / system / gutenberg.php
vikappointments / libraries / system Last commit date
assets.php 1 month ago body.php 4 years ago builder.php 1 month ago cron.php 4 years ago feedback.php 4 years ago gutenberg.php 2 years ago install.php 1 month ago mce.php 4 years ago rssfeeds.php 5 months ago screen.php 4 years ago
gutenberg.php
280 lines
1 <?php
2 /**
3 * @package VikAppointments - Libraries
4 * @subpackage system
5 * @author E4J s.r.l.
6 * @copyright Copyright (C) 2023 E4J s.r.l. All Rights Reserved.
7 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
8 * @link https://vikwp.com
9 */
10
11 // No direct access
12 defined('ABSPATH') or die('No script kiddies please!');
13
14 /**
15 * Class used to provide support for Gutenberg editor.
16 *
17 * @since 1.0
18 */
19 class VikAppointmentsGutenberg
20 {
21 /**
22 * Attaches the necessary scripts to handle the shortcode event.
23 *
24 * @return void
25 */
26 public static function registerShortcodesScript()
27 {
28 /**
29 * Make sure Gutenberg is up and running to avoid
30 * any fatal errors, as the register_block_type()
31 * function may be not available on old instances.
32 */
33 if (!function_exists('register_block_type'))
34 {
35 return false;
36 }
37
38 // register the script declaring the reusable functions for Gutenberg
39 wp_register_script(
40 'vikappointments-gutenberg-tools',
41 VIKAPPOINTMENTS_CORE_MEDIA_URI . 'js/gutenberg-tools.js',
42 ['wp-blocks', 'wp-element', 'wp-i18n'],
43 VIKAPPOINTMENTS_SOFTWARE_VERSION
44 );
45
46 // register the script that contains all the JS functions used
47 // to implement a new block for Gutenberg editor
48 wp_register_script(
49 'vikappointments-gutenberg-shortcodes',
50 VIKAPPOINTMENTS_CORE_MEDIA_URI . 'js/gutenberg-shortcodes.js',
51 ['wp-blocks', 'wp-element', 'wp-i18n', 'jquery'],
52 VIKAPPOINTMENTS_SOFTWARE_VERSION
53 );
54
55 // register the style that contains all the CSS rules used
56 // to stylize the blocks for Gutenberg editor
57 wp_register_style(
58 'vikappointments-gutenberg-shortcodes',
59 VIKAPPOINTMENTS_CORE_MEDIA_URI . 'css/gutenberg-shortcodes.css',
60 [],
61 VIKAPPOINTMENTS_SOFTWARE_VERSION
62 );
63
64 // create a new block type, which must provide the script and the
65 // style we defined in the previous piece of code (script/style ID)
66 register_block_type('vikappointments/gutenberg-shortcodes', [
67 'editor_script_handles' => [
68 'vikappointments-gutenberg-tools',
69 'vikappointments-gutenberg-shortcodes',
70 ],
71 'editor_style_handles' => [
72 'vikappointments-gutenberg-shortcodes',
73 ],
74 'render_callback' => function($config, $content) {
75 if (!empty($config['shortcode']))
76 {
77 $html = do_shortcode($config['shortcode']);
78
79 ob_start();
80 wp_print_styles();
81 $html .= ob_get_contents();
82 ob_end_clean();
83
84 return $html;
85 }
86
87 return $content;
88 },
89 'attributes' => [
90 'toggler' => [
91 'type' => 'boolean',
92 'default' => 0,
93 ],
94 'shortcode' => [
95 'type' => 'string',
96 'default' => '',
97 ],
98 ],
99 ]);
100
101 // pass the block configuration to the script previously loaded
102 wp_localize_script(
103 'vikappointments-gutenberg-shortcodes',
104 'VIKAPPOINTMENTS_SHORTCODES_BLOCK',
105 static::getConfig()
106 );
107
108 // force WordPress to load the translations from VikAppointments
109 wp_set_script_translations('vikappointments-gutenberg-shortcodes', 'vikappointments');
110 }
111
112 /**
113 * Creates the configuration object to use for the block.
114 *
115 * @return array
116 *
117 * @since 1.2.12
118 */
119 protected static function getConfig()
120 {
121 // do not elaborate the configuration for the gutenberg blocks in case we are in the
122 // front-end or in case the plugin in use starts with "com_vik"
123 if (!is_admin() || preg_match("/^com_vik/", JFactory::getApplication()->input->get('option', '')))
124 {
125 return [];
126 }
127
128 $languages = [];
129
130 foreach (JLanguage::getKnownLanguages() as $tag => $lang)
131 {
132 $languages[] = [
133 'tag' => $tag,
134 'name' => $lang['nativeName'],
135 ];
136 }
137
138 $uri = VAPApplication::getInstance();
139 $ajaxUrl = $uri->ajaxUrl('admin-ajax.php?action=vikappointments&task=shortcode.save');
140 $ajaxUrl = $uri->addUrlCSRF($ajaxUrl);
141
142 return [
143 'shortcodes' => static::getShortcodes(),
144 'views' => static::getPages(),
145 'languages' => $languages,
146 'ajaxurl' => $ajaxUrl,
147 ];
148 }
149
150 /**
151 * Returns the list containing all the configured shortcodes.
152 *
153 * @return object[]
154 *
155 * @since 1.2.12
156 */
157 protected static function getShortcodes()
158 {
159 // get shortcode model
160 $model = JModel::getInstance('vikappointments', 'shortcodes', 'admin');
161
162 // obtain a categorized shortcodes list
163 $shortcodes = [];
164
165 foreach ($model->all() as $s)
166 {
167 $title = JText::translate($s->title);
168
169 if (!isset($shortcodes[$title]))
170 {
171 $shortcodes[$title] = [];
172 }
173
174 $shortcodes[$title][] = $s;
175 }
176
177 return $shortcodes;
178 }
179
180 /**
181 * Returns the list containing all the supported site pages that can be
182 * rendered through a shortcode.
183 *
184 * @return object[]
185 *
186 * @since 1.2.12
187 */
188 protected static function getPages()
189 {
190 $views = [];
191
192 // get all the views that contain a default.xml file
193 // [0] : base path
194 // [1] : query
195 // [2] : true for recursive search
196 // [3] : true to return full paths
197 $files = JFolder::files(VAPBASE . DIRECTORY_SEPARATOR . 'views', 'default.xml', true, true);
198
199 foreach ($files as $file)
200 {
201 // retrieve the view ID from the path: /views/[ID]/tmpl/default.xml
202 if (preg_match("/[\/\\\\]views[\/\\\\](.*?)[\/\\\\]tmpl[\/\\\\]default\.xml$/i", $file, $matches))
203 {
204 $id = $matches[1];
205 // load the XML form
206 $form = JForm::getInstance('vikappointments.' . $id, $file);
207
208 $fields = [];
209
210 foreach ($form->getFields() as $field)
211 {
212 try
213 {
214 // get form field
215 $field = JFormField::getInstance($field);
216 }
217 catch (Throwable $error)
218 {
219 // prevent a fatal error in case of outdated adapter
220 JLoader::import('adapter.form.fields.text');
221 $field = new JFormFieldText($field);
222 }
223
224 // obtain field layout data
225 $displayData = array_merge(
226 [
227 'type' => $field->type,
228 'layout' => $field->layoutId,
229 'label' => JText::translate($field->label ?? ''),
230 'description' => strip_tags(JText::translate($field->description ?? '')),
231 'showon' => $field->showon,
232 ],
233 $field->getLayoutData()
234 );
235
236 // normalize options structure
237 if (isset($displayData['options']) && is_array($displayData['options']))
238 {
239 $options = [];
240
241 foreach ($displayData['options'] as $value => $label)
242 {
243 if (is_object($label) || is_array($label))
244 {
245 $label = (object) $label;
246
247 $options[] = [
248 'label' => JText::translate($label->text),
249 'value' => $label->value,
250 ];
251 }
252 else
253 {
254 $options[] = [
255 'label' => JText::translate($label),
256 'value' => $value,
257 ];
258 }
259 }
260
261 $displayData['options'] = $options;
262 }
263
264 $fields[] = $displayData;
265 }
266
267 // get the view title
268 $views[] = [
269 'type' => $id,
270 'name' => JText::translate((string) $form->getXml()->layout->attributes()->title),
271 'desc' => JText::translate((string) $form->getXml()->layout->message),
272 'fields' => $fields,
273 ];
274 }
275 }
276
277 return $views;
278 }
279 }
280