PluginProbe
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News / 4.0.7
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News v4.0.7
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 2.3.5 2.3.6 2.4.0 2.4.1 2.4.10 2.4.11 2.4.12 2.4.13 2.4.14 2.4.15 2.4.16 2.4.17 2.4.18 2.4.19 2.4.2 2.4.20 2.4.21 All 88 releases
post-carousel / admin / page-builder / divi5 / server / index.php

index.php in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 4.0.7, at admin/page-builder/divi5/server/index.php

260 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Divi 5 Module - Server Side Rendering
4 *
5 * @package Smart_Post_Show_Pro
6 * @subpackage Smart_Post_Show_Pro/admin/PageBuilders/Divi5
7 * @since 4.0.0
8 */
9
10 namespace SmartPostShow\Admin\PageBuilders\Divi5;
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit; // Cannot access directly.
14 }
15
16 use ET\Builder\Framework\DependencyManagement\Interfaces\DependencyInterface;
17 use ET\Builder\Packages\ModuleLibrary\ModuleRegistration;
18 use ET\Builder\Packages\Module\Module;
19 use ET\Builder\Packages\Module\Layout\Components\ModuleElements\ModuleElements;
20
21
22 /**
23 * Smart Post Show Pro Divi 5 Module - Server Side.
24 *
25 * @since 4.0.0
26 */
27 class D5SmartPostShowProModule implements DependencyInterface {
28
29 /**
30 * Module instance for singleton pattern.
31 *
32 * @var D5SmartPostShowProModule
33 */
34 private static $instance = null;
35
36 /**
37 * Get singleton instance.
38 *
39 * @since 4.0.0
40 *
41 * @return D5SmartPostShowProModule
42 */
43 public static function get_instance() {
44 if ( null === self::$instance ) {
45 self::$instance = new self();
46 }
47 return self::$instance;
48 }
49
50 /**
51 * Loads the module and registers render callback.
52 * Called by Divi 5's dependency tree system.
53 *
54 * @since 4.0.0
55 *
56 * @return void
57 */
58 public function load() {
59 $module_json_folder_path = SP_PC_PATH . 'blocks/build/divi5/';
60
61 // Register module immediately - don't hook into init.
62 ModuleRegistration::register_module(
63 $module_json_folder_path,
64 array(
65 'render_callback' => array( __CLASS__, 'render_callback' ),
66 )
67 );
68 }
69
70 /**
71 * Render callback for the module.
72 *
73 * @since 4.0.0
74 *
75 * @param array $attrs Module attributes.
76 * @param string $content Module content.
77 * @param \WP_Block $block Block object.
78 * @param ModuleElements $elements ModuleElements instance.
79 * @return string Rendered HTML.
80 */
81 public static function render_callback( $attrs, $content, $block, $elements ) {
82 // Extract template_id from nested attrs structure.
83 $template_id = '0';
84 if ( isset( $attrs['templateId']['innerContent']['desktop']['value'] ) ) {
85 $template_id = $attrs['templateId']['innerContent']['desktop']['value'];
86 }
87
88 // Convert to integer for comparison.
89 $template_id = absint( $template_id );
90
91 if ( empty( $template_id ) || 0 === $template_id ) {
92 $template_html = self::error_message( esc_html__( 'Please Select a Saved Template', 'post-carousel' ) );
93 } else {
94 // Check if template exists and is published.
95 $template_post = get_post( $template_id );
96 if ( ! $template_post || 'publish' !== $template_post->post_status ) {
97 $template_html = self::error_message( esc_html__( 'Template not found or not published.', 'post-carousel' ) );
98 } elseif ( empty( $template_post->post_content ) ) {
99 $template_html = self::error_message( esc_html__( 'Template content is empty.', 'post-carousel' ) );
100 } else {
101 // Render the shortcode.
102 $template_html = do_shortcode( '[smart_post id="' . absint( $template_id ) . '"]' );
103 }
104 }
105
106 // Check if in Divi 5 editor mode for CSS.
107 $is_editor = self::is_divi5_builder_editor();
108 if ( $is_editor && $template_id > 0 ) {
109 // Enqueue CSS for the template in builder mode.
110 self::enqueue_template_dynamic_css( $template_id );
111 }
112
113 // Use Module::render() for proper Divi 5 rendering in both frontend and visual builder.
114 return Module::render(
115 array(
116 // Frontend only params.
117 'orderIndex' => $block->parsed_block['orderIndex'] ?? 0,
118 'storeInstance' => $block->parsed_block['storeInstance'] ?? '',
119
120 // Visual builder params.
121 'attrs' => $attrs,
122 'elements' => $elements,
123 'id' => $block->parsed_block['id'] ?? '',
124 'moduleClassName' => 'spsp_divi5_smart_post_show',
125 'name' => $block->block_type->name ?? 'spsp/divi5-smart-post-show',
126 'classnamesFunction' => array( __CLASS__, 'module_classnames' ),
127 'moduleCategory' => $block->block_type->category ?? 'module',
128 'children' => self::render_module_inner( $template_html, $template_id ),
129 )
130 );
131 }
132
133 /**
134 * Render module inner content.
135 *
136 * @since 4.0.0
137 *
138 * @param string $template_html Rendered template HTML.
139 * @param int $template_id Template ID.
140 * @return string Module inner HTML.
141 */
142 private static function render_module_inner( $template_html, $template_id ) {
143 // Module inner container.
144 return sprintf(
145 '<div class="et_pb_module_inner spsp-divi5-testimonial-wrapper" data-builder-template-id="%s">%s</div>',
146 esc_attr( $template_id ),
147 $template_html
148 );
149 }
150
151 /**
152 * Module classnames callback.
153 *
154 * @since 4.0.0
155 *
156 * @param array $args Callback arguments.
157 * @return void
158 */
159 public static function module_classnames( $args ) {
160 $classnames_instance = $args['classnamesInstance'] ?? null;
161 $attrs = $args['attrs'] ?? array();
162
163 if ( $classnames_instance && method_exists( $classnames_instance, 'add' ) ) {
164 // Add element classnames.
165 $classnames_instance->add( 'spsp_divi5_smart_post_show' );
166 }
167 }
168
169 /**
170 * Check if the current request is for Divi 5 Builder.
171 *
172 * @since 4.0.0
173 *
174 * @return bool True if in Divi 5 builder context.
175 */
176 protected static function is_divi5_builder_editor() {
177 // Check Divi Frontend Builder.
178 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce not required for builder context check.
179 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- isset() check only, value not used.
180 if ( isset( $_GET['et_fb'] ) ) {
181 return true;
182 }
183
184 // Check if Divi is enabled.
185 if ( function_exists( 'et_core_is_fb_enabled' ) && et_core_is_fb_enabled() ) {
186 return true;
187 }
188
189 // Check Divi AJAX requests.
190 if ( wp_doing_ajax() && isset( $_REQUEST['action'] ) && 0 === strpos( sanitize_key( wp_unslash( $_REQUEST['action'] ) ), 'et_' ) ) {
191 return true;
192 }
193
194 return false;
195 }
196
197 /**
198 * Enqueue CSS for template in Divi 5 builder.
199 * Follows the same pattern as Elementor and Oxygen integrations.
200 *
201 * @since 4.0.0
202 *
203 * @param int $template_id Template post ID.
204 * @return void
205 */
206 protected static function enqueue_template_dynamic_css( $template_id ) {
207 // Prevent duplicate CSS generation for the same template in current request.
208 static $generated_templates = array();
209 if ( isset( $generated_templates[ $template_id ] ) ) {
210 return;
211 }
212
213 // Mark this template as processed.
214 $generated_templates[ $template_id ] = true;
215
216 $upload_dir = wp_upload_dir();
217 $css_file = $upload_dir['basedir'] . '/smart-post-show/static/sp-post-' . $template_id . '.css';
218 $css_url = $upload_dir['baseurl'] . '/smart-post-show/static/sp-post-' . $template_id . '.css';
219
220 // Enqueue CSS file if exists (same pattern as Elementor/Oxygen).
221 if ( file_exists( $css_file ) ) {
222 echo '<link rel="stylesheet" href="' . esc_url( $css_url . '?v=' . filemtime( $css_file ) ) . '">'; // phpcs:ignore -- WordPress.Security.EscapeOutput.OutputNotEscaped
223 }
224
225 // Get and output dynamic CSS from meta (same pattern as Elementor/Oxygen).
226 $dynamic_css = get_post_meta( $template_id, '_sp_smart_css', true );
227 if ( ! empty( $dynamic_css ) ) {
228 echo '<style>' . $dynamic_css . '</style>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
229 }
230
231 // Echo Google Fonts directly.
232 $font_lists = get_post_meta( $template_id, '_sp_smart_fonts', true );
233 if ( ! empty( $font_lists ) && is_array( $font_lists ) ) {
234 $font_lists = array_unique( $font_lists );
235 foreach ( $font_lists as $font ) {
236 if ( ! empty( $font ) ) {
237 echo '<link rel="stylesheet" href="' . esc_url( 'https://fonts.googleapis.com/css?family=' . $font ) . '">'; // phpcs:ignore -- WordPress.Security.EscapeOutput.OutputNotEscaped
238 }
239 }
240 }
241 }
242
243 /**
244 * Generate error message HTML.
245 *
246 * @since 4.0.0
247 *
248 * @param string $message Error message.
249 * @return string Error HTML.
250 */
251 protected static function error_message( $message ) {
252 return sprintf(
253 '<div style="text-align:center;padding:20px;border:2px dashed #ccc;color:#999;font-size:14px;">%s</div>',
254 esc_html( $message )
255 );
256 }
257 }
258
259 D5SmartPostShowProModule::get_instance()->load();
260