class-fl-builder-ui-settings-forms.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907
  1. <?php
  2. /**
  3. * Handles logic for UI settings forms.
  4. *
  5. * @since 2.0
  6. */
  7. class FLBuilderUISettingsForms {
  8. /**
  9. * An array of JS templates for custom form tabs and
  10. * sections that need to be loaded.
  11. *
  12. * @since 2.0
  13. * @var int $form_templates
  14. */
  15. static private $form_templates = array();
  16. /**
  17. * @since 2.0
  18. * @return void
  19. */
  20. static public function init() {
  21. add_action( 'wp', __CLASS__ . '::render_settings_config' );
  22. add_action( 'wp_enqueue_scripts', __CLASS__ . '::enqueue_settings_config', 11 );
  23. add_action( 'wp_footer', __CLASS__ . '::init_js_config', 1 );
  24. add_action( 'wp_footer', __CLASS__ . '::render_js_templates', 11 );
  25. }
  26. /**
  27. * Adds an inline script for general settings config and
  28. * one for module settings config.
  29. *
  30. * @since 2.0.7
  31. * @return void
  32. */
  33. static public function enqueue_settings_config() {
  34. global $wp_the_query;
  35. if ( FLBuilderModel::is_builder_active() ) {
  36. $url = FLBuilderModel::get_edit_url( $wp_the_query->post->ID ) . '&fl_builder_load_settings_config';
  37. $script = 'var s = document.createElement("script");s.type = "text/javascript";s.src = "%s";document.head.appendChild(s);';
  38. $config = sprintf( $script, $url );
  39. $modules = sprintf( $script, $url . '=modules' );
  40. wp_add_inline_script( 'fl-builder', $config );
  41. wp_add_inline_script( 'fl-builder-min', $config );
  42. wp_add_inline_script( 'fl-builder', $modules );
  43. wp_add_inline_script( 'fl-builder-min', $modules );
  44. }
  45. }
  46. /**
  47. * Renders the JS config for settings forms for the current page if requested
  48. * and dies early so it can be loaded from a script tag.
  49. *
  50. * @since 2.0.7
  51. * @return void
  52. */
  53. static public function render_settings_config() {
  54. if ( FLBuilderModel::is_builder_active() && isset( $_GET['fl_builder_load_settings_config'] ) ) {
  55. $type = sanitize_key( $_GET['fl_builder_load_settings_config'] );
  56. $handler = 'FLBuilderUISettingsForms::compress_settings_config';
  57. if ( 'modules' === $type ) {
  58. $settings = FLBuilderUISettingsForms::get_modules_js_config();
  59. } else {
  60. $settings = FLBuilderUISettingsForms::get_js_config();
  61. }
  62. if ( @ini_get( 'zlib.output_compression' ) ) { // @codingStandardsIgnoreLine
  63. @ini_set( 'zlib.output_compression', 'Off' ); // @codingStandardsIgnoreLine
  64. $handler = null;
  65. }
  66. header( 'Content-Type: application/javascript' );
  67. ob_start( $handler );
  68. include FL_BUILDER_DIR . 'includes/ui-settings-config.php';
  69. ob_end_flush();
  70. die();
  71. }
  72. }
  73. /**
  74. * Attempts to use the output buffer gzip handler to compress
  75. * the settings config. We have to do it this way to prevent
  76. * errors we were running into on some hosts.
  77. *
  78. * @since 2.1.0.2
  79. * @param string $buffer $mode
  80. * @return string
  81. */
  82. static public function compress_settings_config( $buffer, $mode ) {
  83. @ob_gzhandler( $buffer, null ); // @codingStandardsIgnoreLine
  84. return $buffer;
  85. }
  86. /**
  87. * Initializes the JS config by calling the get method early on
  88. * wp_footer (before the UI renders). This needs to be done so
  89. * changes to the builder's form config arrays are made before the
  90. * JS templates are printed.
  91. *
  92. *
  93. * @since 2.0.1.1
  94. * @return void
  95. */
  96. static public function init_js_config() {
  97. self::get_js_config();
  98. self::get_modules_js_config();
  99. }
  100. /**
  101. * Returns the JS config for all settings forms except
  102. * modules which are loaded in a separate request.
  103. *
  104. * @since 2.0
  105. * @return array
  106. */
  107. static public function get_js_config() {
  108. return array(
  109. 'forms' => self::prep_forms_for_js_config( FLBuilderModel::$settings_forms ),
  110. 'editables' => self::prep_editables_for_js_config(),
  111. 'nodes' => self::prep_node_settings_for_js_config(),
  112. 'attachments' => self::prep_attachments_for_js_config(),
  113. 'settings' => array(
  114. 'global' => FLBuilderModel::get_global_settings(),
  115. 'layout' => FLBuilderModel::get_layout_settings(),
  116. ),
  117. 'defaults' => array(
  118. 'row' => FLBuilderModel::get_row_defaults(),
  119. 'column' => FLBuilderModel::get_col_defaults(),
  120. 'modules' => FLBuilderModel::get_module_defaults(),
  121. 'forms' => self::prep_form_defaults_for_js_config( FLBuilderModel::$settings_forms ),
  122. ),
  123. );
  124. }
  125. /**
  126. * Returns the JS config for all modules.
  127. *
  128. * @since 2.0.7
  129. * @return array
  130. */
  131. static public function get_modules_js_config() {
  132. return array(
  133. 'modules' => self::prep_module_forms_for_js_config(),
  134. );
  135. }
  136. /**
  137. * Returns only the node JS config for settings forms.
  138. *
  139. * @since 2.0
  140. * @return array
  141. */
  142. static public function get_node_js_config() {
  143. return array(
  144. 'nodes' => self::prep_node_settings_for_js_config(),
  145. 'attachments' => self::prep_attachments_for_js_config(),
  146. );
  147. }
  148. /**
  149. * Prepares form defaults for the JS config.
  150. *
  151. * @since 2.0
  152. * @param array $forms
  153. * @return array
  154. */
  155. static private function prep_form_defaults_for_js_config( $forms ) {
  156. $defaults = array();
  157. foreach ( $forms as $form_key => $form ) {
  158. if ( isset( $form['tabs'] ) ) {
  159. $defaults[ $form_key ] = FLBuilderModel::get_settings_form_defaults( $form_key );
  160. }
  161. }
  162. return $defaults;
  163. }
  164. /**
  165. * Prepares forms for the JS config.
  166. *
  167. * @since 2.0
  168. * @param array $forms
  169. * @return array
  170. */
  171. static private function prep_forms_for_js_config( $forms ) {
  172. foreach ( $forms as $form_key => &$form ) {
  173. if ( ! isset( $form['tabs'] ) ) {
  174. continue;
  175. }
  176. foreach ( $form['tabs'] as $tab_key => &$tab ) {
  177. if ( isset( $tab['template'] ) ) {
  178. self::$form_templates[ $tab['template']['id'] ] = $tab['template']['file'];
  179. }
  180. if ( ! isset( $tab['sections'] ) ) {
  181. continue;
  182. }
  183. foreach ( $tab['sections'] as $section_key => &$section ) {
  184. if ( isset( $section['file'] ) && FL_BUILDER_DIR . 'includes/service-settings.php' === $section['file'] ) {
  185. $section['template'] = array(
  186. 'id' => 'fl-builder-service-settings',
  187. 'file' => FL_BUILDER_DIR . 'includes/ui-service-settings.php',
  188. );
  189. unset( $section['file'] );
  190. }
  191. if ( isset( $section['template'] ) ) {
  192. self::$form_templates[ $section['template']['id'] ] = $section['template']['file'];
  193. }
  194. if ( ! isset( $section['fields'] ) ) {
  195. continue;
  196. }
  197. foreach ( $section['fields'] as $field_key => &$field ) {
  198. self::prep_field_for_js_config( $field, $field_key, $form_key );
  199. }
  200. }
  201. }
  202. }
  203. return $forms;
  204. }
  205. /**
  206. * Prepares a field for the JS config.
  207. *
  208. * @since 2.0
  209. * @param array $field
  210. * @param string $field_key
  211. * @param string $form_key
  212. * @return void
  213. */
  214. static private function prep_field_for_js_config( &$field, $field_key = '', $form_key = '' ) {
  215. /**
  216. * This filter hook replaces pre-2.0 `fl_builder_render_settings_field` one.
  217. *
  218. * @param array $field An array of setup data for the field.
  219. * @param string $field_key The field name/key.
  220. * @param string $form_key Module/form key.
  221. */
  222. $field = apply_filters( 'fl_builder_field_js_config', $field, $field_key, $form_key );
  223. // Convert class to className for JS compat.
  224. if ( isset( $field['class'] ) ) {
  225. $field['className'] = $field['class'];
  226. }
  227. // Select fields
  228. if ( 'select' === $field['type'] ) {
  229. if ( is_string( $field['options'] ) && is_callable( $field['options'] ) ) {
  230. $field['options'] = call_user_func( $field['options'] );
  231. } else {
  232. $field['options'] = (array) $field['options'];
  233. }
  234. }
  235. }
  236. /**
  237. * Gathers and prepares module forms for the JS config.
  238. *
  239. * @since 2.0
  240. * @return array
  241. */
  242. static public function prep_module_forms_for_js_config() {
  243. $module_forms = array();
  244. foreach ( FLBuilderModel::$modules as $module ) {
  245. $css = '';
  246. $js = '';
  247. if ( file_exists( $module->dir . 'css/settings.css' ) ) {
  248. $css .= '<link class="fl-builder-settings-css" rel="stylesheet" href="' . $module->url . 'css/settings.css" />';
  249. }
  250. if ( file_exists( $module->dir . 'js/settings.js' ) ) {
  251. $js .= '<script class="fl-builder-settings-js" src="' . $module->url . 'js/settings.js"></script>';
  252. }
  253. $module_forms[ $module->slug ] = array(
  254. 'title' => $module->name,
  255. 'tabs' => $module->form,
  256. 'assets' => array(
  257. 'css' => $css,
  258. 'js' => $js,
  259. ),
  260. );
  261. }
  262. return self::prep_forms_for_js_config( $module_forms );
  263. }
  264. /**
  265. * Gathers and prepares inline module editing data for the JS config.
  266. *
  267. * @since 2.1
  268. * @return array
  269. */
  270. static public function prep_editables_for_js_config() {
  271. $editables = array();
  272. foreach ( FLBuilderModel::$modules as $module ) {
  273. $fields = FLBuilderModel::get_settings_form_fields( $module->form );
  274. foreach ( $fields as $key => $field ) {
  275. if ( 'code' === $field['type'] ) {
  276. continue;
  277. }
  278. if ( ! isset( $field['preview'] ) ) {
  279. continue;
  280. }
  281. if ( ! isset( $field['preview']['type'] ) || 'text' !== $field['preview']['type'] ) {
  282. continue;
  283. }
  284. if ( ! isset( $field['preview']['selector'] ) ) {
  285. continue;
  286. }
  287. if ( ! isset( $editables[ $module->slug ] ) ) {
  288. $editables[ $module->slug ] = array();
  289. }
  290. $editables[ $module->slug ][ $key ] = array(
  291. 'selector' => $field['preview']['selector'],
  292. 'field' => array(
  293. 'name' => $key,
  294. 'type' => $field['type'],
  295. ),
  296. );
  297. }
  298. }
  299. return $editables;
  300. }
  301. /**
  302. * Gathers and prepares node settings for the JS config.
  303. *
  304. * @since 2.0
  305. * @return array
  306. */
  307. static public function prep_node_settings_for_js_config() {
  308. $layout_data = FLBuilderModel::get_layout_data();
  309. $node_settings = array();
  310. foreach ( $layout_data as $node_id => $node ) {
  311. if ( ! is_object( $node ) || ! isset( $node->settings ) || ! is_object( $node->settings ) ) {
  312. continue;
  313. }
  314. $node_settings[ $node_id ] = FLBuilderModel::get_node_settings( $node, false );
  315. }
  316. return $node_settings;
  317. }
  318. /**
  319. * Gathers and prepares attachments for the JS config.
  320. *
  321. * @since 2.0
  322. * @return array
  323. */
  324. static private function prep_attachments_for_js_config() {
  325. $layout_data = FLBuilderModel::get_layout_data();
  326. $attachments = array();
  327. foreach ( $layout_data as $node ) {
  328. if ( ! isset( $node->settings ) || ! is_object( $node->settings ) ) {
  329. continue;
  330. }
  331. if ( 'row' === $node->type ) {
  332. $fields = FLBuilderModel::get_settings_form_fields( FLBuilderModel::$settings_forms['row']['tabs'] );
  333. } elseif ( 'column' === $node->type ) {
  334. $fields = FLBuilderModel::get_settings_form_fields( FLBuilderModel::$settings_forms['col']['tabs'] );
  335. } elseif ( 'module' === $node->type && isset( FLBuilderModel::$modules[ $node->settings->type ] ) ) {
  336. $fields = FLBuilderModel::get_settings_form_fields( FLBuilderModel::$modules[ $node->settings->type ]->form );
  337. } else {
  338. continue;
  339. }
  340. foreach ( $node->settings as $key => $value ) {
  341. // Look for image attachments.
  342. if ( strstr( $key, '_src' ) ) {
  343. $base = str_replace( '_src', '', $key );
  344. if ( isset( $node->settings->$base ) && is_numeric( $node->settings->$base ) ) {
  345. $id = $node->settings->$base;
  346. $data = self::prep_attachment_for_js_config( $id );
  347. if ( $data ) {
  348. $attachments[ $id ] = $data;
  349. }
  350. }
  351. }
  352. // Look for video attachments.
  353. if ( isset( $fields[ $key ] ) && 'video' === $fields[ $key ]['type'] ) {
  354. if ( is_numeric( $value ) ) {
  355. $id = $value;
  356. $data = self::prep_attachment_for_js_config( $id );
  357. if ( $data ) {
  358. $attachments[ $id ] = $data;
  359. }
  360. }
  361. }
  362. }
  363. }
  364. return $attachments;
  365. }
  366. /**
  367. * Prepares a single attachment for the JS config.
  368. *
  369. * @since 2.0
  370. * @param int $id
  371. * @return array|bool
  372. */
  373. static private function prep_attachment_for_js_config( $id ) {
  374. $url = wp_get_attachment_url( $id );
  375. if ( ! $url ) {
  376. return false;
  377. }
  378. $filename = wp_basename( $url );
  379. $base_url = str_replace( $filename, '', $url );
  380. $meta = wp_get_attachment_metadata( $id );
  381. $sizes = array();
  382. $possible_sizes = apply_filters( 'image_size_names_choose', array(
  383. 'thumbnail' => __( 'Thumbnail' ),
  384. 'medium' => __( 'Medium' ),
  385. 'large' => __( 'Large' ),
  386. 'full' => __( 'Full Size' ),
  387. ) );
  388. if ( isset( $meta['sizes'] ) ) {
  389. foreach ( $meta['sizes'] as $size_key => $size ) {
  390. if ( ! isset( $possible_sizes[ $size_key ] ) ) {
  391. continue;
  392. }
  393. $sizes[ $size_key ] = array(
  394. 'url' => $base_url . $size['file'],
  395. 'filename' => $size['file'],
  396. 'width' => $size['width'],
  397. 'height' => $size['height'],
  398. );
  399. }
  400. }
  401. if ( ! isset( $sizes['full'] ) ) {
  402. $sizes['full'] = array(
  403. 'url' => $url,
  404. 'filename' => isset( $meta['file'] ) ? $meta['file'] : $filename,
  405. 'width' => isset( $meta['width'] ) ? $meta['width'] : '',
  406. 'height' => isset( $meta['height'] ) ? $meta['height'] : '',
  407. );
  408. }
  409. return array(
  410. 'id' => $id,
  411. 'url' => $url,
  412. 'filename' => $filename,
  413. 'sizes' => apply_filters( 'fl_builder_photo_sizes_select', $sizes ),
  414. );
  415. }
  416. /**
  417. * Renders the JS templates for settings forms.
  418. *
  419. * @since 2.0
  420. * @return void
  421. */
  422. static public function render_js_templates() {
  423. if ( ! FLBuilderModel::is_builder_active() ) {
  424. return;
  425. }
  426. include FL_BUILDER_DIR . 'includes/ui-settings-form.php';
  427. include FL_BUILDER_DIR . 'includes/ui-settings-form-row.php';
  428. include FL_BUILDER_DIR . 'includes/ui-field.php';
  429. $fields = glob( FL_BUILDER_DIR . 'includes/ui-field-*.php' );
  430. $custom = apply_filters( 'fl_builder_custom_fields', array() );
  431. foreach ( $fields as $path ) {
  432. $slug = str_replace( array( 'ui-field-', '.php' ), '', basename( $path ) );
  433. echo '<script type="text/html" id="tmpl-fl-builder-field-' . $slug . '">';
  434. include $path;
  435. echo '</script>';
  436. }
  437. foreach ( $custom as $type => $path ) {
  438. echo '<script type="text/html" id="tmpl-fl-builder-field-' . $type . '">';
  439. include $path;
  440. echo '</script>';
  441. }
  442. foreach ( self::$form_templates as $id => $path ) {
  443. if ( file_exists( $path ) ) {
  444. echo '<script type="text/html" id="tmpl-' . $id . '">';
  445. include $path;
  446. echo '</script>';
  447. }
  448. }
  449. }
  450. /**
  451. * Pre-renders legacy settings tabs, sections and fields for
  452. * new modules that are currently being sent to the frontend.
  453. *
  454. * @since 2.0
  455. * @param string $type
  456. * @param object $settings
  457. * @return array
  458. */
  459. static public function pre_render_legacy_module_settings( $type, $settings ) {
  460. $data = array(
  461. 'tabs' => array(),
  462. 'sections' => array(),
  463. 'fields' => array(),
  464. 'settings' => $settings,
  465. 'node_id' => null,
  466. );
  467. $custom = apply_filters( 'fl_builder_custom_fields', array() );
  468. foreach ( FLBuilderModel::$modules[ $type ]->form as $tab_id => $tab ) {
  469. if ( isset( $tab['file'] ) ) {
  470. $data['tabs'][] = $tab_id;
  471. }
  472. if ( ! isset( $tab['sections'] ) ) {
  473. continue;
  474. }
  475. foreach ( $tab['sections'] as $section_id => $section ) {
  476. if ( isset( $section['file'] ) ) {
  477. $data['sections'][] = array(
  478. 'tab' => $tab_id,
  479. 'section' => $section_id,
  480. );
  481. }
  482. if ( ! isset( $section['fields'] ) ) {
  483. continue;
  484. }
  485. foreach ( $section['fields'] as $field_id => $field ) {
  486. $is_core = file_exists( FL_BUILDER_DIR . 'includes/ui-field-' . $field['type'] . '.php' );
  487. $is_custom = isset( $custom[ $field['type'] ] );
  488. if ( ! $is_core && ! $is_custom ) {
  489. $data['fields'][] = $field_id;
  490. }
  491. }
  492. }
  493. }
  494. return self::render_legacy_settings( $data, $type, 'module', null );
  495. }
  496. /**
  497. * Renders legacy settings tabs, sections and fields.
  498. *
  499. * @since 2.0
  500. * @param array $data
  501. * @param string $form
  502. * @param string $group
  503. * @param string $lightbox
  504. * @return array
  505. */
  506. static public function render_legacy_settings( $data, $form, $group, $lightbox ) {
  507. $response = array(
  508. 'lightbox' => $lightbox,
  509. 'tabs' => array(),
  510. 'sections' => array(),
  511. 'fields' => array(),
  512. 'extras' => array(),
  513. );
  514. // Get the form tabs.
  515. if ( 'general' === $group ) {
  516. $tabs = FLBuilderModel::$settings_forms[ $form ]['tabs'];
  517. } elseif ( 'module' === $group ) {
  518. $tabs = FLBuilderModel::$modules[ $form ]->form;
  519. }
  520. // Get the form fields.
  521. $fields = FLBuilderModel::get_settings_form_fields( $tabs );
  522. // Get the settings.
  523. if ( $data['node_id'] ) {
  524. $layout_data = FLBuilderModel::get_layout_data();
  525. $settings = $layout_data[ $data['node_id'] ]->settings;
  526. } else {
  527. $settings = isset( $data['settings'] ) ? (object) $data['settings'] : new stdClass();
  528. }
  529. // Render legacy custom fields.
  530. if ( isset( $data['fields'] ) ) {
  531. foreach ( $data['fields'] as $name ) {
  532. ob_start();
  533. self::render_settings_field( $name, (array) $fields[ $name ], $settings );
  534. $response['fields'][ $name ] = ob_get_clean();
  535. }
  536. }
  537. // Render legacy field extras with the before and after actions.
  538. foreach ( $fields as $name => $field ) {
  539. if ( in_array( $name, $response['fields'] ) ) {
  540. continue;
  541. }
  542. $value = isset( $settings->$name ) ? $settings->$name : '';
  543. $is_multiple = isset( $field['multiple'] ) ? $field['multiple'] : false;
  544. if ( $is_multiple ) {
  545. $before = array();
  546. $after = array();
  547. foreach ( $value as $repeater_item_value ) {
  548. ob_start();
  549. do_action( 'fl_builder_before_control', $name, $repeater_item_value, $field, $settings );
  550. do_action( 'fl_builder_before_control_' . $field['type'], $name, $value, $field, $settings );
  551. $before[] = ob_get_clean();
  552. ob_start();
  553. do_action( 'fl_builder_after_control_' . $field['type'], $name, $value, $field, $settings );
  554. do_action( 'fl_builder_after_control', $name, $repeater_item_value, $field, $settings );
  555. $after[] = ob_get_clean();
  556. }
  557. } else {
  558. ob_start();
  559. do_action( 'fl_builder_before_control', $name, $value, $field, $settings );
  560. do_action( 'fl_builder_before_control_' . $field['type'], $name, $value, $field, $settings );
  561. $before = ob_get_clean();
  562. ob_start();
  563. do_action( 'fl_builder_after_control_' . $field['type'], $name, $value, $field, $settings );
  564. do_action( 'fl_builder_after_control', $name, $value, $field, $settings );
  565. $after = ob_get_clean();
  566. }
  567. if ( ! empty( $before ) || ! empty( $after ) ) {
  568. $response['extras'][ $name ] = array(
  569. 'multiple' => $is_multiple,
  570. 'before' => $before,
  571. 'after' => $after,
  572. );
  573. }
  574. }
  575. // Render legacy custom sections.
  576. if ( isset( $data['sections'] ) ) {
  577. foreach ( $data['sections'] as $section_data ) {
  578. $tab = $section_data['tab'];
  579. $name = $section_data['section'];
  580. $section = $tabs[ $tab ]['sections'][ $name ];
  581. if ( file_exists( $section['file'] ) ) {
  582. if ( ! isset( $response['sections'][ $tab ] ) ) {
  583. $response['sections'][ $tab ] = array();
  584. }
  585. ob_start();
  586. include $section['file'];
  587. $response['sections'][ $tab ][ $name ] = ob_get_clean();
  588. }
  589. }
  590. }
  591. // Render legacy custom tabs.
  592. if ( isset( $data['tabs'] ) ) {
  593. foreach ( $data['tabs'] as $name ) {
  594. $tab = $tabs[ $name ];
  595. if ( FL_BUILDER_DIR . 'includes/loop-settings.php' === $tab['file'] ) {
  596. $tab['file'] = FL_BUILDER_DIR . 'includes/ui-loop-settings.php';
  597. }
  598. if ( file_exists( $tab['file'] ) ) {
  599. ob_start();
  600. include $tab['file'];
  601. $response['tabs'][ $name ] = ob_get_clean();
  602. }
  603. }
  604. }
  605. return $response;
  606. }
  607. /**
  608. * Renders a settings via PHP. This method is only around for
  609. * backwards compatibility with third party settings forms that are
  610. * still being rendered via AJAX. Going forward, all settings forms
  611. * should be rendered on the frontend using FLBuilderSettingsForms.render.
  612. *
  613. * @since 2.0
  614. * @param array $form The form data.
  615. * @param object $settings The settings data.
  616. * @return array
  617. */
  618. static public function render_settings( $form = array(), $settings ) {
  619. $defaults = array(
  620. 'class' => '',
  621. 'attrs' => '',
  622. 'title' => '',
  623. 'badges' => array(),
  624. 'tabs' => array(),
  625. 'buttons' => array(),
  626. 'settings' => $settings,
  627. );
  628. // Legacy filter for the config.
  629. $form = apply_filters( 'fl_builder_settings_form_config', array_merge( $defaults, $form ) );
  630. // Setup the class var to be safe in JS.
  631. $form['className'] = $form['class'];
  632. unset( $form['class'] );
  633. // Get the form ID.
  634. foreach ( $form['tabs'] as $tab ) {
  635. $form['id'] = $tab['form_id'];
  636. break;
  637. }
  638. // We don't need to send tab data back.
  639. unset( $form['tabs'] );
  640. // Render and return!
  641. ob_start();
  642. include FL_BUILDER_DIR . 'includes/ui-legacy-settings.php';
  643. $html = ob_get_clean();
  644. return array(
  645. 'html' => $html,
  646. );
  647. }
  648. /**
  649. * Renders a settings form via PHP. This method is only around for
  650. * backwards compatibility with third party settings forms that are
  651. * still being rendered via AJAX. Going forward, all settings forms
  652. * should be rendered on the frontend using FLBuilderSettingsForms.render.
  653. *
  654. * @since 2.0
  655. * @param string $type The type of form to render.
  656. * @param object $settings The settings data.
  657. * @return array
  658. */
  659. static public function render_settings_form( $type = null, $settings = null ) {
  660. $form = FLBuilderModel::get_settings_form( $type );
  661. if ( isset( $settings ) && ! empty( $settings ) ) {
  662. $defaults = FLBuilderModel::get_settings_form_defaults( $type );
  663. $settings = (object) array_merge( (array) $defaults, (array) $settings );
  664. } else {
  665. $settings = FLBuilderModel::get_settings_form_defaults( $type );
  666. }
  667. return self::render_settings(array(
  668. 'title' => $form['title'],
  669. 'tabs' => $form['tabs'],
  670. ), $settings);
  671. }
  672. /**
  673. * Renders a settings field via PHP. This method is only around for
  674. * backwards compatibility with third party settings forms that are
  675. * still being rendered via AJAX. Going forward, all settings forms
  676. * should be rendered on the frontend using FLBuilderSettingsForms.render.
  677. *
  678. * @since 2.0
  679. * @param string $name The field name.
  680. * @param array $field An array of setup data for the field.
  681. * @param object $settings Form settings data object.
  682. * @return void
  683. */
  684. static public function render_settings_field( $name, $field, $settings = null ) {
  685. /**
  686. * Use this filter to modify the config array for a field before it is rendered.
  687. * @see fl_builder_render_settings_field
  688. * @link https://kb.wpbeaverbuilder.com/article/117-plugin-filter-reference
  689. * @since 2.0
  690. */
  691. $field = apply_filters( 'fl_builder_render_settings_field', $field, $name, $settings ); // Allow field settings filtering first
  692. $i = null;
  693. $is_multiple = isset( $field['multiple'] ) && true === (bool) $field['multiple'];
  694. $supports_multiple = 'editor' != $field['type'] && 'photo' != $field['type'] && 'service' != $field['type'];
  695. $settings = ! $settings ? new stdClass() : $settings;
  696. $preview = isset( $field['preview'] ) ? json_encode( $field['preview'] ) : json_encode( array(
  697. 'type' => 'refresh',
  698. ) );
  699. $row_class = isset( $field['row_class'] ) ? ' ' . $field['row_class'] : '';
  700. $responsive = false;
  701. $responsive_fields = array( 'unit' );
  702. $root_name = $name;
  703. $global_settings = FLBuilderModel::get_global_settings();
  704. $value = isset( $settings->$name ) ? $settings->$name : '';
  705. // Use a default value if not set in the settings.
  706. if ( ! isset( $settings->$name ) && isset( $field['default'] ) ) {
  707. $value = $field['default'];
  708. }
  709. // Check to see if responsive is enabled for this field.
  710. if ( $global_settings->responsive_enabled && isset( $field['responsive'] ) && ! $is_multiple && in_array( $field['type'], $responsive_fields ) ) {
  711. $responsive = $field['responsive'];
  712. }
  713. if ( file_exists( FL_BUILDER_DIR . 'includes/ui-field-' . $field['type'] . '.php' ) ) {
  714. // Render old calls to *core* fields with JS.
  715. include FL_BUILDER_DIR . 'includes/ui-legacy-field.php';
  716. } else {
  717. // Render old calls to *custom* fields with PHP.
  718. if ( $is_multiple && $supports_multiple ) {
  719. $values = $value;
  720. $arr_name = $name;
  721. $name .= '[]';
  722. echo '<tbody id="fl-field-' . $root_name . '" class="fl-field fl-builder-field-multiples" data-type="form" data-preview=\'' . $preview . '\'>';
  723. for ( $i = 0; $i < count( $values ); $i++ ) {
  724. $value = $values[ $i ];
  725. echo '<tr class="fl-builder-field-multiple" data-field="' . $arr_name . '">';
  726. include FL_BUILDER_DIR . 'includes/ui-legacy-custom-field.php';
  727. echo '<td class="fl-builder-field-actions">';
  728. echo '<i class="fl-builder-field-move fas fa-arrows-alt"></i>';
  729. echo '<i class="fl-builder-field-copy far fa-copy"></i>';
  730. echo '<i class="fl-builder-field-delete fas fa-times"></i>';
  731. echo '</td>';
  732. echo '</tr>';
  733. }
  734. echo '<tr>';
  735. if ( empty( $field['label'] ) ) {
  736. echo '<td colspan="2">';
  737. } else {
  738. echo '<td>&nbsp;</td><td>';
  739. }
  740. echo '<a href="javascript:void(0);" onclick="return false;" class="fl-builder-field-add fl-builder-button" data-field="' . $arr_name . '">' . sprintf( _x( 'Add %s', 'Field name to add.', 'fl-builder' ), $field['label'] ) . '</a>';
  741. echo '</td>';
  742. echo '</tr>';
  743. echo '</tbody>';
  744. } else {
  745. echo '<tr id="fl-field-' . $name . '" class="fl-field' . $row_class . '" data-type="' . $field['type'] . '" data-preview=\'' . $preview . '\'>';
  746. include FL_BUILDER_DIR . 'includes/ui-legacy-custom-field.php';
  747. echo '</tr>';
  748. }
  749. }
  750. }
  751. /**
  752. * Renders the markup for the icon selector.
  753. *
  754. * @since 2.0
  755. * @return array
  756. */
  757. static public function render_icon_selector() {
  758. $icon_sets = FLBuilderIcons::get_sets();
  759. ob_start();
  760. include FL_BUILDER_DIR . 'includes/icon-selector.php';
  761. $html = ob_get_clean();
  762. return array(
  763. 'html' => $html,
  764. );
  765. }
  766. }
  767. FLBuilderUISettingsForms::init();