PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / 2.5.1
Forumax – AI Powered Advanced Community Forum Plugin v2.5.1
2.5.1 2.5.0 2.4.4 2.4.3 2.4.2 2.4.1 2.4.0 trunk 1.0.8 1.1.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 All 31 releases
bbp-core / includes / template-functions.php

template-functions.php in Forumax – AI Powered Advanced Community Forum Plugin 2.5.1, at includes/template-functions.php

404 lines 12.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Template Functions for Forumax
4 *
5 * @package Forumax
6 */
7
8 defined( 'ABSPATH' ) || exit;
9
10 /**
11 * Register external template stack locations
12 * @return void
13 */
14 add_action( 'after_setup_theme', 'forumax_register_external_templates', 5 );
15 function forumax_register_external_templates() {
16
17 /**
18 * Forumax plugin templates - HIGH PRIORITY
19 * These are the main Forumax styled templates
20 */
21 bbp_register_template_stack( fn() => trailingslashit( FORUMAX_PATH . 'templates' ), 1 );
22
23 /**
24 * Theme override templates (only /forumax/ folder) - HIGHEST PRIORITY
25 * Allows themes to customize Forumax templates if needed
26 */
27 foreach ( forumax_get_theme_override_dirs() as $dir ) {
28 bbp_register_template_stack( fn() => trailingslashit( $dir ), 0 );
29 }
30 }
31
32 /**
33 * Get theme template directories that can override Forumax templates.
34 * Only checks for /forumax/ folder - theme's /bbpress/ folder is NOT used
35 * because Forumax provides its own styled templates.
36 *
37 * @return array
38 */
39 function forumax_get_theme_override_dirs() {
40 $dirs = [];
41 $themes = [ get_template_directory(), get_stylesheet_directory() ];
42
43 foreach ( array_unique( $themes ) as $theme ) {
44 $path = trailingslashit( $theme ) . 'forumax/';
45 if ( is_dir( $path ) ) {
46 $dirs[] = $path;
47 }
48 }
49
50 return $dirs;
51 }
52
53 /**
54 * Extend bbPress template locations
55 */
56 add_filter( 'bbp_get_template_locations', 'forumax_extend_template_locations', 10, 2 );
57 function forumax_extend_template_locations( $locations ) {
58
59 foreach ( [ 'forumax', 'bbpress' ] as $slug ) {
60 if ( ! in_array( $slug, $locations, true ) ) {
61 array_unshift( $locations, $slug );
62 }
63 }
64
65 return $locations;
66 }
67
68 /**
69 * Detect Hello theme family (Hello Elementor, Hello Biz, and child themes).
70 *
71 * @return bool
72 */
73 function forumax_is_hello_theme() {
74 // Runs on every bbPress template lookup; resolve it once per request/theme.
75 static $cache = array();
76
77 $stylesheet = get_stylesheet();
78 $template = get_template();
79 $key = $stylesheet . '|' . $template;
80
81 if ( isset( $cache[ $key ] ) ) {
82 return $cache[ $key ];
83 }
84
85 $hello_slugs = array( 'hello-elementor', 'hello-biz' );
86
87 $cache[ $key ] = false;
88 foreach ( $hello_slugs as $slug ) {
89 if ( 0 === strpos( $template, $slug ) || 0 === strpos( $stylesheet, $slug ) ) {
90 $cache[ $key ] = true;
91 break;
92 }
93 }
94
95 return $cache[ $key ];
96 }
97
98 /**
99 * Ensure Forumax templates are preferred on Hello theme.
100 *
101 * @param array $stack Template stack locations.
102 * @return array
103 */
104 add_filter( 'bbp_get_template_stack', 'forumax_force_templates_on_hello', 1 );
105 function forumax_force_templates_on_hello( $stack ) {
106 if ( ! forumax_is_hello_theme() || ! function_exists( 'bbp_add_template_stack_locations' ) ) {
107 return $stack;
108 }
109
110 $paths = bbp_add_template_stack_locations( array( trailingslashit( FORUMAX_PATH . 'templates' ) ) );
111 foreach ( array_reverse( (array) $paths ) as $path ) {
112 array_unshift( $stack, $path );
113 }
114
115 return array_values( array_unique( $stack ) );
116 }
117
118 /**
119 * Force Forumax forum archive template on Hello theme.
120 *
121 * Uses template_include filter (which runs after all template hierarchy filters)
122 * because Hello Elementor doesn't have archive.php, so archive_template filter
123 * never fires - WordPress falls back to index.php directly.
124 *
125 * @param string $template Current template path.
126 * @return string
127 */
128 add_filter( 'template_include', 'forumax_force_forum_archive_template_on_hello', 99 );
129 function forumax_force_forum_archive_template_on_hello( $template ) {
130 if ( ! forumax_is_hello_theme() || ! function_exists( 'bbp_is_forum_archive' ) ) {
131 return $template;
132 }
133
134 // Only override on bbPress forum archive pages.
135 if ( bbp_is_forum_archive() ) {
136 $hello_template = FORUMAX_PATH . 'templates/hello-archive-forum.php';
137 if ( file_exists( $hello_template ) ) {
138 return $hello_template;
139 }
140 }
141
142 return $template;
143 }
144
145 /**
146 * Force Forumax bbPress user profile template on Hello themes.
147 *
148 * Hello Elementor/Hello Biz can fall back to their 404 template when bbPress
149 * user rewrite rules are missing/out-of-date. This guarantees rendering of
150 * the user profile screen for URLs like `/forums/users/<nicename>/`.
151 *
152 * @param string $template Current template path.
153 * @return string
154 */
155 add_filter( 'template_include', 'forumax_force_user_profile_template_on_hello', 98 );
156 function forumax_force_user_profile_template_on_hello( $template ) {
157 if ( ! forumax_is_hello_theme() || ! function_exists( 'bbp_get_root_slug' ) ) {
158 return $template;
159 }
160
161 if ( ! isset( $_SERVER['REQUEST_URI'] ) ) {
162 return $template;
163 }
164
165 $path = (string) wp_parse_url( (string) $_SERVER['REQUEST_URI'], PHP_URL_PATH );
166 $path = trim( $path, '/' );
167 if ( '' === $path ) {
168 return $template;
169 }
170
171 $root_slug = trim( (string) bbp_get_root_slug(), '/' );
172 if ( '' === $root_slug ) {
173 return $template;
174 }
175
176 // Require /{root}/ prefix.
177 $root_prefix = $root_slug . '/';
178 if ( 0 !== strpos( $path, $root_prefix ) ) {
179 return $template;
180 }
181
182 $after_root = substr( $path, strlen( $root_prefix ) );
183 $parts = array_values( array_filter( explode( '/', (string) $after_root ) ) );
184 if ( count( $parts ) < 2 ) {
185 return $template;
186 }
187
188 $user_base = trim( (string) get_option( '_bbp_user_slug', 'users' ), '/' );
189 if ( '' === $user_base ) {
190 $user_base = 'users';
191 }
192
193 $alt_base = ( 'users' === $user_base ) ? 'user' : 'users';
194 if ( $parts[0] !== $user_base && $parts[0] !== $alt_base ) {
195 return $template;
196 }
197
198 $user_nicename = sanitize_title( (string) $parts[1] );
199 if ( '' === $user_nicename ) {
200 return $template;
201 }
202
203 $the_user = get_user_by( 'slug', $user_nicename );
204 if ( empty( $the_user ) || empty( $the_user->ID ) || ( function_exists( 'bbp_user_has_profile' ) && ! bbp_user_has_profile( $the_user->ID ) ) ) {
205 return $template;
206 }
207
208 // Pass data to the template.
209 set_query_var( 'forumax_hello_user_id', (int) $the_user->ID );
210 set_query_var( 'forumax_hello_user_section', isset( $parts[2] ) ? sanitize_title( (string) $parts[2] ) : '' );
211
212 $hello_template = FORUMAX_PATH . 'templates/hello-single-user.php';
213 if ( file_exists( $hello_template ) ) {
214 return $hello_template;
215 }
216
217 return $template;
218 }
219
220 /**
221 * Add rewrite aliases for bbPress user profiles.
222 *
223 * Some setups (or migrations) end up with links like `/forums/users/admin/`
224 * while the active bbPress "User base" might be `user` (or vice versa).
225 * Injecting aliases at runtime avoids 404s without requiring a rewrite flush.
226 *
227 * @param array $rules
228 * @return array
229 */
230 add_filter( 'rewrite_rules_array', 'forumax_add_bbpress_user_rewrite_aliases', 20 );
231 function forumax_add_bbpress_user_rewrite_aliases( $rules ) {
232 if ( ! function_exists( 'bbp_get_root_slug' ) || ! function_exists( 'bbp_get_user_rewrite_id' ) ) {
233 return $rules;
234 }
235
236 $root_slug = trim( (string) bbp_get_root_slug(), '/' );
237 if ( '' === $root_slug ) {
238 return $rules;
239 }
240
241 $user_base = trim( (string) get_option( '_bbp_user_slug', 'users' ), '/' );
242 if ( '' === $user_base ) {
243 $user_base = 'users';
244 }
245
246 $alt_base = ( 'users' === $user_base ) ? 'user' : 'users';
247
248 $root_regex = preg_quote( $root_slug, '!' );
249 $bases = array_values( array_unique( array( $user_base, $alt_base ) ) );
250 $add = array();
251
252 foreach ( $bases as $base ) {
253 $base_regex = preg_quote( $base, '!' );
254
255 // User profile root: /{root}/{users|user}/{nicename}/
256 $profile_rule = '^' . $root_regex . '/' . $base_regex . '/([^/]+)/?$';
257 if ( ! isset( $rules[ $profile_rule ] ) ) {
258 $add[ $profile_rule ] = 'index.php?' . bbp_get_user_rewrite_id() . '=$matches[1]';
259 }
260 }
261
262 return $add + $rules;
263 }
264
265 /**
266 * Map bbPress user profile URLs at runtime (no rewrite flush).
267 *
268 * When rewrite rules are missing/out-of-date, Hello themes often fall through
269 * to their 404 template for URLs like `/forums/users/<nicename>/`. Other themes
270 * may mask the issue by having alternate templates/routes.
271 *
272 * This ensures Hello themes always populate bbPress query vars early enough
273 * for bbPress's `bbp_parse_query()` to flag the request as a user profile.
274 *
275 * @param WP $wp
276 * @return void
277 */
278 add_action( 'parse_request', 'forumax_map_bbpress_user_request_on_hello', 1 );
279 function forumax_map_bbpress_user_request_on_hello( $wp ) {
280 if ( ! forumax_is_hello_theme() || is_admin() ) {
281 return;
282 }
283
284 if ( ! ( $wp instanceof WP ) ) {
285 return;
286 }
287
288 if ( ! function_exists( 'bbp_get_root_slug' ) || ! function_exists( 'bbp_get_user_rewrite_id' ) ) {
289 return;
290 }
291
292 $user_rewrite_id = bbp_get_user_rewrite_id();
293 if ( empty( $user_rewrite_id ) ) {
294 return;
295 }
296
297 // If bbPress already matched, don't interfere.
298 if ( ! empty( $wp->query_vars[ $user_rewrite_id ] ) ) {
299 return;
300 }
301
302 $request = isset( $wp->request ) ? trim( (string) $wp->request, '/' ) : '';
303 if ( '' === $request ) {
304 return;
305 }
306
307 $root_slug = trim( (string) bbp_get_root_slug(), '/' );
308 if ( '' === $root_slug ) {
309 return;
310 }
311
312 $root_prefix = $root_slug . '/';
313 if ( 0 !== strpos( $request, $root_prefix ) ) {
314 return;
315 }
316
317 $after_root = substr( $request, strlen( $root_prefix ) );
318 if ( '' === $after_root ) {
319 return;
320 }
321
322 $user_base = trim( (string) get_option( '_bbp_user_slug', 'users' ), '/' );
323 if ( '' === $user_base ) {
324 $user_base = 'users';
325 }
326
327 $alt_base = ( 'users' === $user_base ) ? 'user' : 'users';
328
329 // Match: (users|user)/{nicename}/(optional section)
330 $base_regex = '(?:' . preg_quote( $user_base, '!' ) . '|' . preg_quote( $alt_base, '!' ) . ')';
331 if ( ! preg_match( '!' . '^' . $base_regex . '/([^/]+)(?:/(.*))?$' . '!' , $after_root, $m ) ) {
332 return;
333 }
334
335 $user_nicename = sanitize_title( $m[1] );
336 $section = isset( $m[2] ) ? trim( (string) $m[2], '/' ) : '';
337
338 if ( '' === $user_nicename ) {
339 return;
340 }
341
342 // Set the primary bbPress user query var.
343 $wp->query_vars[ $user_rewrite_id ] = $user_nicename;
344
345 // Also set the bbPress query name for consistency.
346 $wp->query_vars['_bbp_query_name'] = 'bbp_single_user';
347
348 // Map optional sections (favorites/subscriptions/topics/replies/engagements/edit).
349 if ( '' !== $section ) {
350 $section_first = explode( '/', $section )[0];
351
352 if ( function_exists( 'bbp_get_edit_slug' ) && ( bbp_get_edit_slug() === $section_first ) ) {
353 $wp->query_vars[ bbp_get_edit_rewrite_id() ] = '1';
354 } elseif ( function_exists( 'bbp_get_user_favorites_slug' ) && ( bbp_get_user_favorites_slug() === $section_first ) ) {
355 $wp->query_vars[ bbp_get_user_favorites_rewrite_id() ] = bbp_get_user_favorites_slug();
356 } elseif ( function_exists( 'bbp_get_user_subscriptions_slug' ) && ( bbp_get_user_subscriptions_slug() === $section_first ) ) {
357 $wp->query_vars[ bbp_get_user_subscriptions_rewrite_id() ] = bbp_get_user_subscriptions_slug();
358 } elseif ( function_exists( 'bbp_get_topic_archive_slug' ) && ( bbp_get_topic_archive_slug() === $section_first ) ) {
359 $wp->query_vars[ bbp_get_user_topics_rewrite_id() ] = '1';
360 } elseif ( function_exists( 'bbp_get_reply_archive_slug' ) && ( bbp_get_reply_archive_slug() === $section_first ) ) {
361 $wp->query_vars[ bbp_get_user_replies_rewrite_id() ] = '1';
362 } elseif ( function_exists( 'bbp_get_user_engagements_slug' ) && ( bbp_get_user_engagements_slug() === $section_first ) ) {
363 $wp->query_vars[ bbp_get_user_engagements_rewrite_id() ] = '1';
364 }
365 }
366 }
367
368 /**
369 * Banner preset background styles
370 *
371 * @return array[]|string[]
372 */
373 function forumax_banner_bg_style() {
374 return [
375 'color' => FORUMAX_IMG . '/options/color.png',
376 'faded-sun' => FORUMAX_IMG . '/options/faded-sun.jpg',
377 'happy-journey' => FORUMAX_IMG . '/options/happy-journey.jpg',
378 'apparent-circle' => FORUMAX_IMG . '/options/apparent-circle.jpg',
379 'soft-weather' => FORUMAX_IMG . '/options/soft-weather.jpg',
380 'romantic-sun' => FORUMAX_IMG . '/options/romantic-sun.jpg',
381 'teal-eclipse' => FORUMAX_IMG . '/options/teal-eclipse.jpg',
382 ];
383 }
384
385
386
387 /**
388 * Image from Settings
389 *
390 * @param string $option_id
391 * @param string $class
392 * @param string $alt
393 */
394 function get_image_from_settings( string $option_id = '', string $class = '', string $alt = '' ):void {
395 $image = forumax_get_opt($option_id) ?? '';
396
397 // Check if the image has an 'id' or a 'url' and display accordingly
398 if ( ! empty($image['id']) ) {
399 echo wp_get_attachment_image($image['id'], 'full', '' );
400 } elseif ( !empty($image['url']) ) {
401 echo "<img src='{$image['url']}'>";
402 }
403 }
404