Completed
Branch BUG-9623-config-log (1352ef)
by
unknown
251:43 queued 237:21
created

EEH_Template   D

Complexity

Total Complexity 112

Size/Duplication

Total Lines 759
Duplicated Lines 1.05 %

Coupling/Cohesion

Components 2
Dependencies 10

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 112
c 1
b 0
f 1
lcom 2
cbo 10
dl 8
loc 759
rs 4.4444

17 Methods

Rating   Name   Duplication   Size   Complexity  
F locate_template() 0 105 22
A is_espresso_theme() 0 3 2
A load_espresso_theme_functions() 0 7 3
B get_espresso_themes() 0 16 5
A get_template_part() 0 12 3
A _find_common_base_path() 0 16 4
B display_template() 0 36 6
B get_object_css_class() 0 22 5
C format_currency() 4 47 10
A pretty_status() 0 6 1
A get_button_or_link() 0 5 2
C get_help_tab_link() 4 16 10
F help_tour_stops_generator() 0 38 13
B status_legend() 0 27 5
C layout_array_as_table() 0 45 7
A paging_html() 0 3 1
D get_paging_html() 0 108 13

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like EEH_Template often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use EEH_Template, and based on these observations, apply Extract Interface, too.

1
<?php
2
if ( ! defined('EVENT_ESPRESSO_VERSION')) { exit('NO direct script access allowed'); }
3
/**
4
 * Event Espresso
5
 *
6
 * Event Registration and Management Plugin for WordPress
7
 *
8
 * @package     Event Espresso
9
 * @author      Event Espresso
10
 * @copyright	  (c)2009-2012 Event Espresso All Rights Reserved.
11
 * @license     http://eventespresso.com/support/terms-conditions/  ** see Plugin Licensing **
12
 * @link        http://www.eventespresso.com
13
 * @version		4.0
14
 */
15
16
17
18
if ( ! function_exists( 'espresso_get_template_part' )) {
19
	/**
20
	 * espresso_get_template_part
21
	 * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
22
	 * so not a very useful function at all except that it adds familiarity PLUS filtering based off of the entire template part name
23
	 *
24
	 * @param string $slug The slug name for the generic template.
25
	 * @param string $name The name of the specialised template.
26
	 * @return string        the html output for the formatted money value
27
	 */
28
	function espresso_get_template_part( $slug = NULL, $name = NULL ) {
29
		EEH_Template::get_template_part( $slug, $name );
30
	}
31
}
32
33
34
35
if ( ! function_exists( 'espresso_get_object_css_class' )) {
36
	/**
37
	 * espresso_get_object_css_class - attempts to generate a css class based on the type of EE object passed
38
	 *
39
	 *
40
	 * @param EE_Base_Class $object the EE object the css class is being generated for
41
	 * @param  string $prefix added to the beginning of the generated class
42
	 * @param  string $suffix added to the end of the generated class
43
	 * @return string
44
	 */
45
	function espresso_get_object_css_class( $object = NULL, $prefix = '', $suffix = '' ) {
46
		return EEH_Template::get_object_css_class( $object, $prefix, $suffix );
47
	}
48
}
49
50
51
52
/**
53
 * class EEH_Template
54
 *
55
 * This is a helper utility class that provides different helpers related to template files.
56
 *
57
 * @package		Event Espresso
58
 * @subpackage	/helpers/EEH_Template.helper.php
59
 * @author		    Darren Ethier, Brent Christensen
60
 *
61
 */
62
class EEH_Template {
63
64
	private static $_espresso_themes = array();
65
66
67
	/**
68
	 * 	is_espresso_theme - returns TRUE or FALSE on whether the currently active WP theme is an espresso theme
69
	 *
70
	 * 	@return boolean
71
	 */
72
	public static function is_espresso_theme() {
73
		return wp_get_theme()->get( 'TextDomain' ) == 'event_espresso' ? TRUE : FALSE;
74
	}
75
76
	/**
77
	 * 	load_espresso_theme_functions - if current theme is an espresso theme, or uses ee theme template parts, then load it's functions.php file ( if not already loaded )
78
	 *
79
	 * 	@return void
80
	 */
81
	public static function load_espresso_theme_functions() {
82
		if ( ! defined( 'EE_THEME_FUNCTIONS_LOADED' )) {
83
			if ( is_readable( EE_PUBLIC . EE_Config::get_current_theme() . DS . 'functions.php' )) {
84
				require_once( EE_PUBLIC . EE_Config::get_current_theme() . DS . 'functions.php' );
85
			}
86
		}
87
	}
88
89
90
	/**
91
	 * 	get_espresso_themes - returns an array of Espresso Child themes located in the /templates/ directory
92
	 *
93
	 * 	@return array
94
	 */
95
	public static function get_espresso_themes() {
96
		if ( empty( EEH_Template::$_espresso_themes )) {
97
			$espresso_themes =  glob( EE_PUBLIC . '*', GLOB_ONLYDIR );
98
			if ( empty( $espresso_themes ) ) {
99
				return array();
100
			}
101
			if (( $key = array_search( 'global_assets', $espresso_themes )) !== FALSE ) {
102
			    unset( $espresso_themes[ $key ] );
103
			}
104
			EEH_Template::$_espresso_themes = array();
105
			foreach ( $espresso_themes as $espresso_theme ) {
106
				EEH_Template::$_espresso_themes[ basename( $espresso_theme ) ] = $espresso_theme;
107
			}
108
		}
109
		return EEH_Template::$_espresso_themes;
110
	}
111
112
113
114
	/**
115
	 * EEH_Template::get_template_part
116
	 * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
117
	 * so not a very useful function at all except that it adds familiarity PLUS filtering based off of the entire template part name
118
	 *
119
	 * @param string $slug The slug name for the generic template.
120
	 * @param string $name The name of the specialised template.
121
	 * @param array  $template_args
122
	 * @param bool   $return_string
123
	 * @return string        the html output for the formatted money value
124
	 */
125
	public static function get_template_part( $slug = NULL, $name = NULL, $template_args = array(), $return_string = FALSE  ) {
126
		do_action( "get_template_part_{$slug}-{$name}", $slug, $name );
127
		$templates = array();
128
		$name = (string) $name;
129
		if ( $name != '' ) {
130
			$templates[] = "{$slug}-{$name}.php";
131
		}
132
		// allow template parts to be turned off via something like: add_filter( 'FHEE__content_espresso_events_tickets_template__display_datetimes', '__return_false' );
133
		if ( apply_filters( "FHEE__EEH_Template__get_template_part__display__{$slug}_{$name}", TRUE )) {
134
			EEH_Template::locate_template( $templates, $template_args, TRUE, $return_string );
135
		}
136
	}
137
138
139
140
	/**
141
	 *    locate_template
142
	 *
143
	 *    locate a template file by looking in the following places, in the following order:
144
	 *        <server path up to>/wp-content/themes/<current active WordPress theme>/
145
	 *        <assumed full absolute server path>
146
	 *        <server path up to>/wp-content/uploads/espresso/templates/<current EE theme>/
147
	 *        <server path up to>/wp-content/uploads/espresso/templates/
148
	 *        <server path up to>/wp-content/plugins/<EE4 folder>/public/<current EE theme>/
149
	 *        <server path up to>/wp-content/plugins/<EE4 folder>/core/templates/<current EE theme>/
150
	 *        <server path up to>/wp-content/plugins/<EE4 folder>/
151
	 *    as soon as the template is found in one of these locations, it will be returned or loaded
152
	 *
153
	 * 		Example:
154
	 * 		  You are using the WordPress Twenty Sixteen theme,
155
	 *        and you want to customize the "some-event.template.php" template,
156
	 * 		  which is located in the "/relative/path/to/" folder relative to the main EE plugin folder.
157
	 * 		  Assuming WP is installed on your server in the "/home/public_html/" folder,
158
	 *        EEH_Template::locate_template() will look at the following paths in order until the template is found:
159
	 *
160
	 *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
161
	 *        /relative/path/to/some-event.template.php
162
	 *        /home/public_html/wp-content/uploads/espresso/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
163
	 *        /home/public_html/wp-content/uploads/espresso/templates/relative/path/to/some-event.template.php
164
	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/public/Espresso_Arabica_2014/relative/path/to/some-event.template.php
165
	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/core/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
166
	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/relative/path/to/some-event.template.php
167
	 *
168
	 * 		  Had you passed an absolute path to your template that was in some other location,
169
	 *        ie: "/absolute/path/to/some-event.template.php"
170
	 * 		  then the search would have been :
171
	 *
172
	 *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
173
	 *        /absolute/path/to/some-event.template.php
174
	 *
175
	 * 		  and stopped there upon finding it in the second location
176
	 *
177
	 * @param array|string $templates array of template file names including extension (or just a single string)
178
	 * @param  array   $template_args an array of arguments to be extracted for use in the template
179
	 * @param  boolean $load          whether to pass the located template path on to the EEH_Template::display_template() method or simply return it
180
	 * @param  boolean $return_string whether to send output immediately to screen, or capture and return as a string
181
	 * @param boolean $check_if_custom If TRUE, this flags this method to return boolean for whether this will generate a custom template or not.
182
	 * 				Used in places where you don't actually load the template, you just want to know if there's a custom version of it.
183
	 * @return mixed
184
	 */
185
	public static function locate_template( $templates = array(), $template_args = array(), $load = TRUE, $return_string = TRUE, $check_if_custom = FALSE ) {
186
		// first use WP locate_template to check for template in the current theme folder
187
		$template_path = locate_template( $templates );
188
189
		if ( $check_if_custom && !empty( $template_path ) )
190
			return TRUE;
191
192
		// not in the theme
193
		if ( empty( $template_path )) {
194
			// not even a template to look for ?
195
			if ( empty( $templates )) {
196
				// get post_type
197
				$post_type = EE_Registry::instance()->REQ->get( 'post_type' );
198
				// get array of EE Custom Post Types
199
				$EE_CPTs = EE_Register_CPTs::get_CPTs();
200
				// build template name based on request
201
				if ( isset( $EE_CPTs[ $post_type ] )) {
202
					$archive_or_single =  is_archive() ? 'archive' : '';
203
					$archive_or_single =  is_single() ? 'single' : $archive_or_single;
204
					$templates = $archive_or_single . '-' . $post_type . '.php';
205
				}
206
			}
207
			// currently active EE template theme
208
			$current_theme = EE_Config::get_current_theme();
209
210
			// array of paths to folders that may contain templates
211
			$template_folder_paths = array(
212
				// first check the /wp-content/uploads/espresso/templates/(current EE theme)/  folder for an EE theme template file
213
				EVENT_ESPRESSO_TEMPLATE_DIR . $current_theme,
214
				// then in the root of the /wp-content/uploads/espresso/templates/ folder
215
				EVENT_ESPRESSO_TEMPLATE_DIR
216
			);
217
218
			//add core plugin folders for checking only if we're not $check_if_custom
219
			if ( ! $check_if_custom ) {
220
				$core_paths = array(
221
					// in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
222
					EE_PUBLIC . $current_theme,
223
					// in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
224
					EE_TEMPLATES . $current_theme,
225
					// or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
226
					EE_PLUGIN_DIR_PATH
227
					);
228
				$template_folder_paths = array_merge( $template_folder_paths, $core_paths );
229
			}
230
231
			// now filter that array
232
			$template_folder_paths = apply_filters( 'FHEE__EEH_Template__locate_template__template_folder_paths', $template_folder_paths );
233
			$templates = is_array( $templates ) ? $templates : array( $templates );
234
			$template_folder_paths = is_array( $template_folder_paths ) ? $template_folder_paths : array( $template_folder_paths );
235
			// array to hold all possible template paths
236
			$full_template_paths = array();
237
238
			EE_Registry::instance()->load_helper('File');
239
			// loop through $templates
240
			foreach ( $templates as $template ) {
241
				// normalize directory separators
242
				$template = EEH_File::standardise_directory_separators( $template );
243
				$file_name = basename( $template );
244
				$template_path_minus_file_name = substr( $template, 0, ( strlen( $file_name ) * -1 ) );
245
				// while looping through all template folder paths
246
				foreach ( $template_folder_paths as $template_folder_path ) {
247
					// normalize directory separators
248
					$template_folder_path = EEH_File::standardise_directory_separators( $template_folder_path );
249
					// determine if any common base path exists between the two paths
250
					$common_base_path = EEH_Template::_find_common_base_path(
251
						array( $template_folder_path, $template_path_minus_file_name )
252
					);
253
					if ( $common_base_path !== '' ) {
254
						// both paths have a common base, so just tack the filename onto our search path
255
						$resolved_path = EEH_File::end_with_directory_separator( $template_folder_path ) . $file_name;
256
					} else {
257
						// no common base path, so let's just concatenate
258
						$resolved_path = EEH_File::end_with_directory_separator( $template_folder_path ) . $template;
259
					}
260
					// build up our template locations array by adding our resolved paths
261
					$full_template_paths[] = $resolved_path;
262
				}
263
				// if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
264
				array_unshift( $full_template_paths, $template );
265
				// path to the directory of the current theme: /wp-content/themes/(current WP theme)/
266
				array_unshift( $full_template_paths, get_stylesheet_directory() . DS . $file_name );
267
			}
268
			// filter final array of full template paths
269
			$full_template_paths = apply_filters( 'FHEE__EEH_Template__locate_template__full_template_paths', $full_template_paths, $file_name );
0 ignored issues
show
Bug introduced by
The variable $file_name does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
270
			// now loop through our final array of template location paths and check each location
271
			foreach ( (array)$full_template_paths as $full_template_path ) {
272
				if ( is_readable( $full_template_path )) {
273
					$template_path = str_replace( array( '\\', '/' ), DIRECTORY_SEPARATOR, $full_template_path );
274
					// hook that can be used to display the full template path that will be used
275
					do_action( 'AHEE__EEH_Template__locate_template__full_template_path', $template_path );
276
					break;
277
				}
278
			}
279
		}
280
		// if we got it and you want to see it...
281
		if ( $template_path && $load && ! $check_if_custom  ) {
282
			if ( $return_string ) {
283
				return EEH_Template::display_template( $template_path, $template_args, TRUE );
284
			} else {
285
				EEH_Template::display_template( $template_path, $template_args, FALSE );
286
			}
287
		}
288
		return $check_if_custom && ! empty( $template_path ) ? TRUE : $template_path;
289
	}
290
291
292
293
	/**
294
	 * _find_common_base_path
295
	 *
296
	 * given two paths, this determines if there is a common base path between the two
297
	 *
298
	 * @param array $paths
299
	 * @return string
300
	 */
301
	protected static function _find_common_base_path( $paths ) {
302
		$last_offset = 0;
303
		$common_base_path = '';
304
		while ( ( $index = strpos( $paths[ 0 ], DS, $last_offset ) ) !== false ) {
305
			$dir_length = $index - $last_offset + 1;
306
			$directory = substr( $paths[ 0 ], $last_offset, $dir_length );
307
			foreach ( $paths as $path ) {
308
				if ( substr( $path, $last_offset, $dir_length ) != $directory ) {
309
					return $common_base_path;
310
				}
311
			}
312
			$common_base_path .= $directory;
313
			$last_offset = $index + 1;
314
		}
315
		return substr( $common_base_path, 0, -1 );
316
	}
317
318
319
320
	/**
321
	 * load and display a template
322
	 * @param bool|string $template_path server path to the file to be loaded, including file name and extension
323
	 * @param  array      $template_args an array of arguments to be extracted for use in the template
324
	 * @param  boolean    $return_string whether to send output immediately to screen, or capture and return as a string
325
	 * @return mixed string
326
	 */
327
	public static function display_template( $template_path = FALSE, $template_args = array(), $return_string = FALSE ) {
328
		//require the template validator for verifying variables are set according to how the template requires
329
		EE_Registry::instance()->load_helper( 'Template_Validator' );
330
331
		/**
332
		 * These two filters are intended for last minute changes to templates being loaded and/or template arg
333
		 * modifications.  NOTE... modifying these things can cause breakage as most templates running through
334
		 * the display_template method are templates we DON'T want modified (usually because of js
335
		 * dependencies etc).  So unless you know what you are doing, do NOT filter templates or template args
336
		 * using this.
337
		 *
338
		 * @since 4.6.0
339
		 */
340
		$template_path = apply_filters( 'FHEE__EEH_Template__display_template__template_path', $template_path );
341
		$template_args = apply_filters( 'FHEE__EEH_Template__display_template__template_args', $template_args );
342
343
		// you gimme nuttin - YOU GET NUTTIN !!
344
		if ( ! $template_path || ! is_readable( $template_path )) {
345
			return '';
346
		}
347
		// if $template_args are not in an array, then make it so
348
		if ( ! is_array( $template_args ) && ! is_object( $template_args )) {
349
			$template_args = array( $template_args );
350
		}
351
		extract( (array) $template_args);
352
353
		if ( $return_string ) {
354
			// because we want to return a string, we are going to capture the output
355
			ob_start();
356
			include( $template_path );
357
			return ob_get_clean();
358
		} else {
359
			include( $template_path );
360
		}
361
		return '';
362
	}
363
364
365
366
367
368
	/**
369
	 * get_object_css_class - attempts to generate a css class based on the type of EE object passed
370
	 *
371
	 *
372
	 * @param EE_Base_Class $object the EE object the css class is being generated for
373
	 * @param  string $prefix added to the beginning of the generated class
374
	 * @param  string $suffix added to the end of the generated class
375
	 * @return string
376
	 */
377
	public static function get_object_css_class( $object = NULL, $prefix = '', $suffix = '' ) {
378
		// in the beginning...
379
		$prefix = ! empty( $prefix ) ? rtrim( $prefix, '-' ) . '-' : '';
380
		// da muddle
381
		$class = '';
382
		// the end
383
		$suffix = ! empty( $suffix ) ? '-' . ltrim( $suffix, '-' ) : '';
384
		// is the passed object an EE object ?
385
		if ( $object instanceof EE_Base_Class ) {
386
			// grab the exact type of object
387
			$obj_class = get_class( $object );
388
			// depending on the type of object...
389
			switch ( $obj_class ) {
390
				// no specifics just yet...
391
				default :
0 ignored issues
show
Unused Code introduced by
// no specifics just yet...($object->name()) : ''; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
392
					$class = strtolower( str_replace( '_', '-', $obj_class ));
393
					$class .= method_exists( $obj_class, 'name' ) ? '-' . sanitize_title( $object->name() ) : '';
394
395
			}
396
		}
397
		return $prefix . $class . $suffix;
398
	}
399
400
401
402
	/**
403
	 * EEH_Template::format_currency
404
	 * This helper takes a raw float value and formats it according to the default config country currency settings, or the country currency settings from the supplied country ISO code
405
	 *
406
	 * @param  float      $amount       raw money value
407
	 * @param  boolean    $return_raw   whether to return the formatted float value only with no currency sign or code
408
	 * @param  boolean    $display_code whether to display the country code (USD). Default = TRUE
409
	 * @param string $CNT_ISO      2 letter ISO code for a country
410
	 * @param string      $cur_code_span_class
411
	 * @return string        the html output for the formatted money value
412
	 */
413
	public static function format_currency( $amount = NULL, $return_raw = FALSE, $display_code = TRUE, $CNT_ISO = '', $cur_code_span_class = 'currency-code' ) {
414
		// ensure amount was received
415
		if ( is_null( $amount ) ) {
416
			$msg = __( 'In order to format currency, an amount needs to be passed.', 'event_espresso' );
417
			EE_Error::add_error( $msg, __FILE__, __FUNCTION__, __LINE__ );
418
			return '';
419
		}
420
		//ensure amount is float
421
		$amount = (float) $amount;
422
		// filter raw amount (allows 0.00 to be changed to "free" for example)
423
		$amount_formatted = apply_filters( 'FHEE__EEH_Template__format_currency__amount', $amount, $return_raw );
424
		// still a number or was amount converted to a string like "free" ?
425
		if ( is_float( $amount_formatted )) {
426
			// was a country ISO code passed ? if so generate currency config object for that country
427
			$mny = $CNT_ISO !== '' ? new EE_Currency_Config( $CNT_ISO ) : NULL;
428
			// verify results
429 View Code Duplication
			if ( ! $mny instanceof EE_Currency_Config ) {
430
				// set default config country currency settings
431
				$mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config ? EE_Registry::instance()->CFG->currency : new EE_Currency_Config();
432
			}
433
			// format float
434
			$amount_formatted = number_format( $amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds );
435
			// add formatting ?
436
			if ( ! $return_raw ) {
437
				// add currency sign
438
				if( $mny->sign_b4 ){
439
					if( $amount >= 0 ){
440
						$amount_formatted = $mny->sign . $amount_formatted;
441
					}else{
442
						$amount_formatted = '-' . $mny->sign . str_replace( '-', '', $amount_formatted );
443
					}
444
445
				}else{
446
					$amount_formatted =  $amount_formatted . $mny->sign;
447
				}
448
449
				// add currency code ?
450
				$amount_formatted = $display_code ? $amount_formatted . ' <span class="' . $cur_code_span_class . '">(' . $mny->code . ')</span>' : $amount_formatted;
451
			}
452
			// filter results
453
			$amount_formatted = apply_filters( 'FHEE__EEH_Template__format_currency__amount_formatted', $amount_formatted, $mny, $return_raw );
454
		}
455
		// clean up vars
456
		unset( $mny );
457
		// return formatted currency amount
458
		return $amount_formatted;
459
	}
460
461
462
463
464
	/**
465
	 * This function is used for outputting the localized label for a given status id in the schema requested (and possibly plural).  The intended use of this function is only for cases where wanting a label outside of a related status model or model object (i.e. in documentation etc.)
466
	 * @param  string  $status_id Status ID matching a registered status in the esp_status table.  If there is no match, then 'Unknown' will be returned.
467
	 * @param  boolean $plural    Whether to return plural or not
468
	 * @param  string  $schema    'UPPER', 'lower', or 'Sentence'
469
	 * @return string             The localized label for the status id.
470
	 */
471
	public static function pretty_status( $status_id, $plural = FALSE, $schema = 'upper' ) {
472
		/** @type EEM_Status $EEM_Status */
473
		$EEM_Status = EE_Registry::instance()->load_model( 'Status' );
474
		$status = $EEM_Status->localized_status( array( $status_id => __( 'unknown', 'event_espresso' )), $plural, $schema );
475
		return $status[ $status_id ];
476
	}
477
478
479
480
	/**
481
	 * This helper just returns a button or link for the given parameters
482
	 * @param  string $url   the url for the link
483
	 * @param  string $label What is the label you want displayed for the button
484
	 * @param  string $class what class is used for the button (defaults to 'button-primary')
485
	 * @param string  $icon
486
	 * @return string 	the html output for the button
487
	 */
488
	public static function get_button_or_link( $url, $label, $class = 'button-primary', $icon = '' ) {
489
		$label = ! empty( $icon ) ? '<span class="' . $icon . '"></span>' . $label : $label;
490
		$button = '<a id="' . sanitize_title_with_dashes($label) . '" href="' . $url . '" class="' . $class . '">' . $label . '</a>';
491
		return $button;
492
	}
493
494
495
496
	/**
497
	 * This returns a generated link that will load the related help tab on admin pages.
498
	 *
499
	 *
500
	 * @param  string     $help_tab_id the id for the connected help tab
501
	 * @param bool|string $page        The page identifier for the page the help tab is on
502
	 * @param bool|string $action      The action (route) for the admin page the help tab is on.
503
	 * @param bool|string $icon_style  (optional) include css class for the style you want to use for the help icon.
504
	 * @param bool|string $help_text   (optional) send help text you want to use for the link if default not to be used
505
	 * @return string              generated link
506
	 */
507
	public static function get_help_tab_link( $help_tab_id, $page = FALSE, $action = FALSE, $icon_style = FALSE, $help_text = FALSE ) {
508
509 View Code Duplication
		if ( ! $page )
510
			$page = isset( $_REQUEST['page'] ) && ! empty( $_REQUEST['page'] ) ? sanitize_key( $_REQUEST['page'] ) : $page;
511
512 View Code Duplication
		if ( ! $action )
513
			$action = isset( $_REQUEST['action'] ) && ! empty( $_REQUEST['action'] ) ? sanitize_key( $_REQUEST['action'] ) : $action;
514
515
		$action = empty($action) ? 'default' : $action;
516
517
518
		$help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
519
		$icon = !$icon_style ? ' dashicons-editor-help' : $icon_style;
520
		$help_text = !$help_text ? '' : $help_text;
521
		return '<a id="' . $help_tab_lnk . '" class="ee-clickable dashicons espresso-help-tab-lnk ee-icon-size-22' . $icon . '" title="' . esc_attr__('Click to open the \'Help\' tab for more information about this feature.', 'event_espresso') . '" > ' . $help_text . ' </a>';
522
	}
523
524
525
526
	/**
527
	 * This helper generates the html structure for the jquery joyride plugin with the given params.
528
	 * @link http://zurb.com/playground/jquery-joyride-feature-tour-plugin
529
	 * @see EE_Admin_Page->_stop_callback() for the construct expected for the $stops param.
530
	 * @param EE_Help_Tour
531
	 * @return string         html
532
	 */
533
	public static function help_tour_stops_generator( EE_Help_Tour $tour ) {
534
		$id = $tour->get_slug();
535
		$stops = $tour->get_stops();
536
537
		$content = '<ol style="display:none" id="' . $id . '">';
538
539
		foreach ( $stops as $stop ) {
540
			$data_id = !empty( $stop['id'] ) ? ' data-id="' . $stop['id'] . '"' : '';
541
			$data_class = empty( $data_id ) && !empty( $stop['class'] ) ? ' data-class="' . $stop['class'] . '"' : '';
542
543
			//if container is set to modal then let's make sure we set the options accordingly
544
			if ( empty( $data_id ) && empty( $data_class ) ) {
545
				$stop['options']['modal'] = true;
546
				$stop['options']['expose'] = true;
547
			}
548
549
			$custom_class = !empty( $stop['custom_class'] ) ? ' class="' . $stop['custom_class'] . '"' : '';
550
			$button_text = !empty( $stop['button_text'] ) ? ' data-button="' . $stop['button_text'] . '"' : '';
551
			$inner_content = isset($stop['content']) ? $stop['content'] : '';
552
553
			//options
554
			if ( isset( $stop['options'] ) && is_array( $stop['options'] ) ) {
555
				$options = ' data-options="';
556
				foreach ( $stop['options'] as $option => $value ) {
557
					$options .= $option . ':' . $value . ';';
558
				}
559
				$options .= '"';
560
			} else {
561
				$options = '';
562
			}
563
564
			//let's put all together
565
			$content .= '<li' . $data_id . $data_class . $custom_class . $button_text . $options . '>' . $inner_content . '</li>';
566
		}
567
568
		$content .= '</ol>';
569
		return $content;
570
	}
571
572
573
574
	/**
575
	 * This is a helper method to generate a status legend for a given status array.
576
	 * Note this will only work if the incoming statuses have a key in the EEM_Status->localized_status() methods status_array.
577
	 *
578
	 * @param  array  $status_array  array of statuses that will make up the legend. In format:
579
	 *      array(
580
	 *          'status_item' => 'status_name'
581
	 *       )
582
	 * @param  string $active_status This is used to indicate what the active status is IF that is to be highlighted in the legend.
583
	 * @throws EE_Error
584
	 * @return string               html structure for status.
585
	 */
586
	public static function status_legend( $status_array, $active_status = '' ) {
587
		if ( !is_array( $status_array ) )
588
			throw new EE_Error( __('The EEH_Template::status_legend helper required the incoming status_array argument to be an array!', 'event_espresso') );
589
590
		$setup_array = array();
591
		foreach ( $status_array as $item => $status ) {
592
			$setup_array[$item] = array(
593
					'class' => 'ee-status-legend ee-status-legend-' . $status,
594
					'desc' => EEH_Template::pretty_status( $status, FALSE, 'sentence' ),
595
					'status' => $status
596
				);
597
		}
598
599
		$content = '<div class="ee-list-table-legend-container">' . "\n";
600
		$content .= '<h3>' . __('Status Legend', 'event_espresso') . '</h3>' . "\n";
601
		$content .= '<dl class="ee-list-table-legend">' . "\n\t";
602
		foreach ( $setup_array as $item => $details ) {
603
			$active_class = $active_status == $details['status'] ? ' class="ee-is-active-status"' : '';
604
			$content .= '<dt id="ee-legend-item-tooltip-' . $item . '"' . $active_class . '>' . "\n\t\t";
605
			$content .= '<span class="' . $details['class'] . '"></span>' . "\n\t\t";
606
			$content .= '<span class="ee-legend-description">' . $details['desc'] . '</span>' . "\n\t";
607
			$content .= '</dt>' . "\n";
608
		}
609
		$content .= '</dl>' . "\n";
610
		$content .= '</div>' . "\n";
611
		return $content;
612
	}
613
614
615
616
	/**
617
	 * Gets HTML for laying out a deeply-nested array (and objects) in a format
618
	 * that's nice for presenting in the wp admin
619
	 * @param mixed $data
620
	 * @return string
621
	 */
622
	public static function layout_array_as_table($data) {
623
	if (is_object($data) || $data instanceof __PHP_Incomplete_Class ) {
624
		$data = (array)$data;
625
	}
626
	EE_Registry::instance()->load_helper('Array');
627
	ob_start();
628
	if (is_array($data)) {
629
		if (EEH_Array::is_associative_array($data)) {
630
			?>
631
			<table class="widefat">
632
				<tbody>
633
					<?php
634
					foreach ($data as $data_key => $data_values) {
635
						?>
636
						<tr>
637
							<td>
638
								<?php echo $data_key;?>
639
							</td>
640
							<td>
641
								<?php echo self::layout_array_as_table($data_values);?>
642
							</td>
643
						</tr>
644
						<?php
645
					}?>
646
				</tbody>
647
			</table>
648
			<?php
649
		}
650
		else {
651
			?>
652
			<ul>
653
				<?php
654
				foreach ($data as $datum) {
655
					echo "<li>"; echo self::layout_array_as_table($datum);echo "</li>";
656
				}?>
657
			</ul>
658
			<?php
659
		}
660
	}
661
	else {
662
		//simple value
663
		echo $data;
664
	}
665
	return ob_get_clean();
666
}
667
668
669
670
	/**
671
	 * wrapper for self::get_paging_html() that simply echos the generated paging html
672
	 *
673
	 * @since 4.4.0
674
	 * @see   self:get_paging_html() for argument docs.
675
	 * @param      $total_items
676
	 * @param      $current
677
	 * @param      $per_page
678
	 * @param      $url
679
	 * @param bool $show_num_field
680
	 * @param string $paged_arg_name
681
	 * @param array $items_label
682
	 *
683
	 * @return string
684
	 */
685
	public static function paging_html( $total_items, $current, $per_page, $url, $show_num_field = TRUE, $paged_arg_name = 'paged', $items_label = array() ) {
686
		echo self::get_paging_html( $total_items, $current, $per_page, $url, $show_num_field, $paged_arg_name, $items_label );
687
	}
688
689
690
691
	/**
692
	 * A method for generating paging similar to WP_List_Table
693
	 *
694
	 * @since 4.4.0
695
	 * @see      wp-admin/includes/class-wp-list-table.php WP_List_Table::pagination()
696
	 *
697
	 * @param  integer $total_items      	How many total items there are to page.
698
	 * @param  integer $current 	 	What the current page is.
699
	 * @param  integer $per_page 		How many items per page.
700
	 * @param  string   $url                  	What the base url for page links is.
701
	 * @param  boolean $show_num_field  Whether to show the input for changing page number.
702
	 * @param  string   $paged_arg_name     The name of the key for the paged query argument.
703
	 * @param  array   $items_label    An array of singular/plural values for the items label:
704
	 *                                 array(
705
	 *                                  'single' => 'item',
706
	 *                                  'plural' => 'items'
707
	 *                                 )
708
	 * @return  string
709
	 */
710
	public static function get_paging_html( $total_items, $current, $per_page, $url, $show_num_field = TRUE, $paged_arg_name = 'paged', $items_label = array() ) {
711
		$page_links = array();
712
		$disable_first = $disable_last = '';
713
		$total_items = (int) $total_items;
714
		$per_page = (int) $per_page;
715
		$current = (int) $current;
716
		$paged_arg_name = empty( $paged_arg_name ) ? 'paged' : sanitize_key( $paged_arg_name );
717
718
		//filter items_label
719
		$items_label = apply_filters(
720
			'FHEE__EEH_Template__get_paging_html__items_label',
721
			$items_label
722
		);
723
724
		if ( empty( $items_label )
725
		     || ! is_array( $items_label )
726
		     || ! isset( $items_label['single'] )
727
		     || ! isset( $items_label['plural'] ) ) {
728
			$items_label = array(
729
				'single' => __( '1 item', 'event_espresso' ),
730
				'plural' => __( '%s items', 'event_espresso' )
731
			);
732
		} else {
733
			$items_label = array(
734
				'single' => '1 ' . esc_html( $items_label['single'] ),
735
				'plural' => '%s ' . esc_html( $items_label['plural'] )
736
			);
737
		}
738
739
		$total_pages = ceil( $total_items / $per_page );
740
741
		if ( $total_pages <= 1 )
742
			return '';
743
744
		$item_label = $total_items > 1 ? sprintf( $items_label['plural'], $total_items ) : $items_label['single'];
745
746
		$output = '<span class="displaying-num">' . $item_label . '</span>';
747
748
		if ( $current === 1 ) {
749
			$disable_first = ' disabled';
750
		}
751
		if ( $current == $total_pages ) {
752
			$disable_last = ' disabled';
753
		}
754
755
		$page_links[] = sprintf( "<a class='%s' title='%s' href='%s'>%s</a>",
756
			'first-page' . $disable_first,
757
			esc_attr__( 'Go to the first page' ),
758
			esc_url( remove_query_arg( $paged_arg_name, $url ) ),
759
			'&laquo;'
760
		);
761
762
		$page_links[] = sprintf(
763
			'<a class="%s" title="%s" href="%s">%s</a>',
764
			'prev-page' . $disable_first,
765
			esc_attr__( 'Go to the previous page' ),
766
			esc_url( add_query_arg( $paged_arg_name, max( 1, $current-1 ), $url ) ),
767
			'&lsaquo;'
768
		);
769
770
		if ( ! $show_num_field ) {
771
			$html_current_page = $current;
772
		} else {
773
			$html_current_page = sprintf( "<input class='current-page' title='%s' type='text' name=$paged_arg_name value='%s' size='%d' />",
774
				esc_attr__( 'Current page' ),
775
				$current,
776
				strlen( $total_pages )
777
			);
778
		}
779
780
		$html_total_pages = sprintf(
781
			'<span class="total-pages">%s</span>',
782
			number_format_i18n( $total_pages )
783
		);
784
		$page_links[] = sprintf(
785
			_x( '%3$s%1$s of %2$s%4$s', 'paging' ),
786
			$html_current_page,
787
			$html_total_pages,
788
			'<span class="paging-input">',
789
			'</span>'
790
		);
791
792
		$page_links[] = sprintf(
793
			'<a class="%s" title="%s" href="%s">%s</a>',
794
			'next-page' . $disable_last,
795
			esc_attr__( 'Go to the next page' ),
796
			esc_url( add_query_arg( $paged_arg_name, min( $total_pages, $current+1 ), $url ) ),
797
			'&rsaquo;'
798
		);
799
800
		$page_links[] = sprintf(
801
			'<a class="%s" title="%s" href="%s">%s</a>',
802
			'last-page' . $disable_last,
803
			esc_attr__( 'Go to the last page' ),
804
			esc_url( add_query_arg( $paged_arg_name, $total_pages, $url ) ),
805
			'&raquo;'
806
		);
807
808
		$output .= "\n" . '<span class="pagination-links">' . join( "\n", $page_links ) . '</span>';
809
		// set page class
810
		if ( $total_pages ) {
811
			$page_class = $total_pages < 2 ? ' one-page' : '';
812
		} else {
813
			$page_class = ' no-pages';
814
		}
815
816
		return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
817
	}
818
819
820
} //end EEH_Template class
821
822
//function convert_zero_to_free( $amount, $return_raw ) {
823
//	// we don't want to mess with requests for unformatted values because those may get used in calculations
824
//	if ( ! $return_raw && ! is_admin() ) {
825
//		$amount = __( 'free', 'event_espresso' );
826
//	}
827
//	return $amount;
828
//}
829
//add_filter( 'FHEE__EEH_Template__format_currency__amount', 'convert_zero_to_free', 10, 2 );
830
831
832 View Code Duplication
if ( ! function_exists( 'espresso_pagination' ) ) {
833
	/**
834
	 *    espresso_pagination
835
	 *
836
	 * @access    public
837
	 * @return    void
838
	 */
839
	function espresso_pagination() {
840
		global $wp_query;
841
		$big = 999999999; // need an unlikely integer
842
		$pagination = paginate_links(
843
		array(
844
		'base'         => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
845
		'format'       => '?paged=%#%',
846
		'current'      => max( 1, get_query_var( 'paged' ) ),
847
		'total'        => $wp_query->max_num_pages,
848
		'show_all'     => true,
849
		'end_size'     => 10,
850
		'mid_size'     => 6,
851
		'prev_next'    => true,
852
		'prev_text'    => __( '&lsaquo; PREV', 'event_espresso' ),
853
		'next_text'    => __( 'NEXT &rsaquo;', 'event_espresso' ),
854
		'type'         => 'plain',
855
		'add_args'     => false,
856
		'add_fragment' => ''
857
		)
858
		);
859
		echo ! empty( $pagination ) ? '<div class="ee-pagination-dv clear">' . $pagination . '</div>' : '';
860
	}
861
}