Completed
Branch BUG-9042-ics-organizer-email (7b2e23)
by
unknown
29:24 queued 16:15
created

EEH_Template::display_template()   C

Complexity

Conditions 8
Paths 7

Size

Total Lines 49
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 24
nc 7
nop 4
dl 0
loc 49
rs 6.1403
c 0
b 0
f 0
1
<?php
2
if (! defined('EVENT_ESPRESSO_VERSION')) {
3
    exit('NO direct script access allowed');
4
}
5
/**
6
 * Event Espresso
7
 * Event Registration and Management Plugin for WordPress
8
 *
9
 * @package           Event Espresso
10
 * @author            Event Espresso
11
 * @copyright      (c)2009-2012 Event Espresso All Rights Reserved.
12
 * @license           http://eventespresso.com/support/terms-conditions/  ** see Plugin Licensing **
13
 * @link              http://www.eventespresso.com
14
 * @version           4.0
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
    {
30
        EEH_Template::get_template_part($slug, $name);
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
     * @param EE_Base_Class $object the EE object the css class is being generated for
40
     * @param  string       $prefix added to the beginning of the generated class
41
     * @param  string       $suffix added to the end of the generated class
42
     * @return string
43
     */
44
    function espresso_get_object_css_class($object = null, $prefix = '', $suffix = '')
45
    {
46
        return EEH_Template::get_object_css_class($object, $prefix, $suffix);
47
    }
48
}
49
50
51
/**
52
 * class EEH_Template
53
 * This is a helper utility class that provides different helpers related to template files.
54
 *
55
 * @package           Event Espresso
56
 * @subpackage        /helpers/EEH_Template.helper.php
57
 * @author            Darren Ethier, Brent Christensen
58
 */
59
class EEH_Template
60
{
61
62
    private static $_espresso_themes = array();
63
64
65
    /**
66
     *    is_espresso_theme - returns TRUE or FALSE on whether the currently active WP theme is an espresso theme
67
     *
68
     * @return boolean
69
     */
70
    public static function is_espresso_theme()
71
    {
72
        return wp_get_theme()->get('TextDomain') == 'event_espresso' ? true : false;
73
    }
74
75
    /**
76
     *    load_espresso_theme_functions - if current theme is an espresso theme, or uses ee theme template parts, then
77
     *    load it's functions.php file ( if not already loaded )
78
     *
79
     * @return void
80
     */
81
    public static function load_espresso_theme_functions()
82
    {
83
        if ( ! defined('EE_THEME_FUNCTIONS_LOADED')) {
84
            if (is_readable(EE_PUBLIC . EE_Config::get_current_theme() . DS . 'functions.php')) {
85
                require_once(EE_PUBLIC . EE_Config::get_current_theme() . DS . 'functions.php');
86
            }
87
        }
88
    }
89
90
91
    /**
92
     *    get_espresso_themes - returns an array of Espresso Child themes located in the /templates/ directory
93
     *
94
     * @return array
95
     */
96
    public static function get_espresso_themes()
97
    {
98
        if (empty(EEH_Template::$_espresso_themes)) {
99
            $espresso_themes = glob(EE_PUBLIC . '*', GLOB_ONLYDIR);
100
            if (empty($espresso_themes)) {
101
                return array();
102
            }
103
            if (($key = array_search('global_assets', $espresso_themes)) !== false) {
104
                unset($espresso_themes[$key]);
105
            }
106
            EEH_Template::$_espresso_themes = array();
107
            foreach ($espresso_themes as $espresso_theme) {
108
                EEH_Template::$_espresso_themes[basename($espresso_theme)] = $espresso_theme;
109
            }
110
        }
111
        return EEH_Template::$_espresso_themes;
112
    }
113
114
115
    /**
116
     * EEH_Template::get_template_part
117
     * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead,
118
     * and doesn't add base versions of files so not a very useful function at all except that it adds familiarity PLUS
119
     * filtering based off of the entire template part name
120
     *
121
     * @param string $slug The slug name for the generic template.
122
     * @param string $name The name of the specialised template.
123
     * @param array  $template_args
124
     * @param bool   $return_string
125
     * @return string        the html output for the formatted money value
126
     */
127
    public static function get_template_part(
128
        $slug = null,
129
        $name = null,
130
        $template_args = array(),
131
        $return_string = false
132
    ) {
133
        do_action("get_template_part_{$slug}-{$name}", $slug, $name);
134
        $templates = array();
135
        $name      = (string)$name;
136
        if ($name != '') {
137
            $templates[] = "{$slug}-{$name}.php";
138
        }
139
        // allow template parts to be turned off via something like: add_filter( 'FHEE__content_espresso_events_tickets_template__display_datetimes', '__return_false' );
140
        if (apply_filters("FHEE__EEH_Template__get_template_part__display__{$slug}_{$name}", true)) {
141
            EEH_Template::locate_template($templates, $template_args, true, $return_string);
142
        }
143
    }
144
145
146
    /**
147
     *    locate_template
148
     *    locate a template file by looking in the following places, in the following order:
149
     *        <server path up to>/wp-content/themes/<current active WordPress theme>/
150
     *        <assumed full absolute server path>
151
     *        <server path up to>/wp-content/uploads/espresso/templates/<current EE theme>/
152
     *        <server path up to>/wp-content/uploads/espresso/templates/
153
     *        <server path up to>/wp-content/plugins/<EE4 folder>/public/<current EE theme>/
154
     *        <server path up to>/wp-content/plugins/<EE4 folder>/core/templates/<current EE theme>/
155
     *        <server path up to>/wp-content/plugins/<EE4 folder>/
156
     *    as soon as the template is found in one of these locations, it will be returned or loaded
157
     *        Example:
158
     *          You are using the WordPress Twenty Sixteen theme,
159
     *        and you want to customize the "some-event.template.php" template,
160
     *          which is located in the "/relative/path/to/" folder relative to the main EE plugin folder.
161
     *          Assuming WP is installed on your server in the "/home/public_html/" folder,
162
     *        EEH_Template::locate_template() will look at the following paths in order until the template is found:
163
     *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
164
     *        /relative/path/to/some-event.template.php
165
     *        /home/public_html/wp-content/uploads/espresso/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
166
     *        /home/public_html/wp-content/uploads/espresso/templates/relative/path/to/some-event.template.php
167
     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/public/Espresso_Arabica_2014/relative/path/to/some-event.template.php
168
     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/core/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
169
     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/relative/path/to/some-event.template.php
170
     *          Had you passed an absolute path to your template that was in some other location,
171
     *        ie: "/absolute/path/to/some-event.template.php"
172
     *          then the search would have been :
173
     *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
174
     *        /absolute/path/to/some-event.template.php
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
180
     *                                      EEH_Template::display_template() method or simply return it
181
     * @param  boolean     $return_string   whether to send output immediately to screen, or capture and return as a
182
     *                                      string
183
     * @param boolean      $check_if_custom If TRUE, this flags this method to return boolean for whether this will
184
     *                                      generate a custom template or not. Used in places where you don't actually
185
     *                                      load the template, you just want to know if there's a custom version of it.
186
     * @return mixed
187
     */
188
    public static function locate_template(
189
        $templates = array(),
190
        $template_args = array(),
191
        $load = true,
192
        $return_string = true,
193
        $check_if_custom = false
194
    ) {
195
        // first use WP locate_template to check for template in the current theme folder
196
        $template_path = locate_template($templates);
197
198
        if ($check_if_custom && ! empty($template_path)) {
199
            return true;
200
        }
201
202
        // not in the theme
203
        if (empty($template_path)) {
204
            // not even a template to look for ?
205
            if (empty($templates)) {
206
                // get post_type
207
                $post_type = EE_Registry::instance()->REQ->get('post_type');
208
                // get array of EE Custom Post Types
209
                $EE_CPTs = EE_Register_CPTs::get_CPTs();
210
                // build template name based on request
211
                if (isset($EE_CPTs[$post_type])) {
212
                    $archive_or_single = is_archive() ? 'archive' : '';
213
                    $archive_or_single = is_single() ? 'single' : $archive_or_single;
214
                    $templates         = $archive_or_single . '-' . $post_type . '.php';
215
                }
216
            }
217
            // currently active EE template theme
218
            $current_theme = EE_Config::get_current_theme();
219
220
            // array of paths to folders that may contain templates
221
            $template_folder_paths = array(
222
                // first check the /wp-content/uploads/espresso/templates/(current EE theme)/  folder for an EE theme template file
223
                EVENT_ESPRESSO_TEMPLATE_DIR . $current_theme,
224
                // then in the root of the /wp-content/uploads/espresso/templates/ folder
225
                EVENT_ESPRESSO_TEMPLATE_DIR,
226
            );
227
228
            //add core plugin folders for checking only if we're not $check_if_custom
229
            if ( ! $check_if_custom) {
230
                $core_paths            = array(
231
                    // in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
232
                    EE_PUBLIC . $current_theme,
233
                    // in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
234
                    EE_TEMPLATES . $current_theme,
235
                    // or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
236
                    EE_PLUGIN_DIR_PATH,
237
                );
238
                $template_folder_paths = array_merge($template_folder_paths, $core_paths);
239
            }
240
241
            // now filter that array
242
            $template_folder_paths = apply_filters('FHEE__EEH_Template__locate_template__template_folder_paths',
243
                $template_folder_paths);
244
            $templates             = is_array($templates) ? $templates : array($templates);
245
            $template_folder_paths = is_array($template_folder_paths) ? $template_folder_paths : array($template_folder_paths);
246
            // array to hold all possible template paths
247
            $full_template_paths = array();
248
249
            // loop through $templates
250
            foreach ($templates as $template) {
251
                // normalize directory separators
252
                $template                      = EEH_File::standardise_directory_separators($template);
253
                $file_name                     = basename($template);
254
                $template_path_minus_file_name = substr($template, 0, (strlen($file_name) * -1));
255
                // while looping through all template folder paths
256
                foreach ($template_folder_paths as $template_folder_path) {
257
                    // normalize directory separators
258
                    $template_folder_path = EEH_File::standardise_directory_separators($template_folder_path);
259
                    // determine if any common base path exists between the two paths
260
                    $common_base_path = EEH_Template::_find_common_base_path(
261
                        array($template_folder_path, $template_path_minus_file_name)
262
                    );
263
                    if ($common_base_path !== '') {
264
                        // both paths have a common base, so just tack the filename onto our search path
265
                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $file_name;
266
                    } else {
267
                        // no common base path, so let's just concatenate
268
                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $template;
269
                    }
270
                    // build up our template locations array by adding our resolved paths
271
                    $full_template_paths[] = $resolved_path;
272
                }
273
                // if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
274
                array_unshift($full_template_paths, $template);
275
                // path to the directory of the current theme: /wp-content/themes/(current WP theme)/
276
                array_unshift($full_template_paths, get_stylesheet_directory() . DS . $file_name);
277
            }
278
            // filter final array of full template paths
279
            $full_template_paths = apply_filters('FHEE__EEH_Template__locate_template__full_template_paths',
280
                $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...
281
            // now loop through our final array of template location paths and check each location
282
            foreach ((array)$full_template_paths as $full_template_path) {
283
                if (is_readable($full_template_path)) {
284
                    $template_path = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $full_template_path);
285
                    // hook that can be used to display the full template path that will be used
286
                    do_action('AHEE__EEH_Template__locate_template__full_template_path', $template_path);
287
                    break;
288
                }
289
            }
290
        }
291
        // if we got it and you want to see it...
292
        if ($template_path && $load && ! $check_if_custom) {
293
            if ($return_string) {
294
                return EEH_Template::display_template($template_path, $template_args, true);
295
            } else {
296
                EEH_Template::display_template($template_path, $template_args, false);
297
            }
298
        }
299
        return $check_if_custom && ! empty($template_path) ? true : $template_path;
300
    }
301
302
303
    /**
304
     * _find_common_base_path
305
     * given two paths, this determines if there is a common base path between the two
306
     *
307
     * @param array $paths
308
     * @return string
309
     */
310
    protected static function _find_common_base_path($paths)
311
    {
312
        $last_offset      = 0;
313
        $common_base_path = '';
314
        while (($index = strpos($paths[0], DS, $last_offset)) !== false) {
315
            $dir_length = $index - $last_offset + 1;
316
            $directory  = substr($paths[0], $last_offset, $dir_length);
317
            foreach ($paths as $path) {
318
                if (substr($path, $last_offset, $dir_length) != $directory) {
319
                    return $common_base_path;
320
                }
321
            }
322
            $common_base_path .= $directory;
323
            $last_offset = $index + 1;
324
        }
325
        return substr($common_base_path, 0, -1);
326
    }
327
328
329
    /**
330
     * load and display a template
331
     *
332
     * @param bool|string $template_path server path to the file to be loaded, including file name and extension
333
     * @param  array      $template_args an array of arguments to be extracted for use in the template
334
     * @param  boolean    $return_string whether to send output immediately to screen, or capture and return as a string
335
     * @param bool        $throw_exceptions if set to true, will throw an exception if the template is either
336
     *                                      not found or is not readable
337
     * @return mixed string
338
     * @throws \DomainException
339
     */
340
	public static function display_template(
341
        $template_path    = false,
342
        $template_args    = array(),
343
        $return_string    = false,
344
        $throw_exceptions = false
345
    ) {
346
347
        /**
348
         * These two filters are intended for last minute changes to templates being loaded and/or template arg
349
         * modifications.  NOTE... modifying these things can cause breakage as most templates running through
350
         * the display_template method are templates we DON'T want modified (usually because of js
351
         * dependencies etc).  So unless you know what you are doing, do NOT filter templates or template args
352
         * using this.
353
         *
354
         * @since 4.6.0
355
         */
356
        $template_path = (string) apply_filters('FHEE__EEH_Template__display_template__template_path', $template_path);
357
        $template_args = (array) apply_filters('FHEE__EEH_Template__display_template__template_args', $template_args);
358
359
        // you gimme nuttin - YOU GET NUTTIN !!
360
        if ( ! $template_path || ! is_readable($template_path)) {
361
            return '';
362
        }
363
        // if $template_args are not in an array, then make it so
364
        if ( ! is_array($template_args) && ! is_object($template_args)) {
365
            $template_args = array($template_args);
366
        }
367
        extract( $template_args, EXTR_SKIP );
368
        // ignore whether template is accessible ?
369
        if ( $throw_exceptions && ! is_readable( $template_path ) ) {
370
            throw new \DomainException(
371
                    esc_html__(
372
                            'Invalid, unreadable, or missing file.',
373
                            'event_espresso'
374
                    )
375
            );
376
        }
377
378
379
        if ($return_string) {
380
            // because we want to return a string, we are going to capture the output
381
            ob_start();
382
            include($template_path);
383
            return ob_get_clean();
384
        } else {
385
            include($template_path);
386
        }
387
        return '';
388
    }
389
390
391
    /**
392
     * get_object_css_class - attempts to generate a css class based on the type of EE object passed
393
     *
394
     * @param EE_Base_Class $object the EE object the css class is being generated for
395
     * @param  string       $prefix added to the beginning of the generated class
396
     * @param  string       $suffix added to the end of the generated class
397
     * @return string
398
     */
399
    public static function get_object_css_class($object = null, $prefix = '', $suffix = '')
400
    {
401
        // in the beginning...
402
        $prefix = ! empty($prefix) ? rtrim($prefix, '-') . '-' : '';
403
        // da muddle
404
        $class = '';
405
        // the end
406
        $suffix = ! empty($suffix) ? '-' . ltrim($suffix, '-') : '';
407
        // is the passed object an EE object ?
408
        if ($object instanceof EE_Base_Class) {
409
            // grab the exact type of object
410
            $obj_class = get_class($object);
411
            // depending on the type of object...
412
            switch ($obj_class) {
413
                // no specifics just yet...
414
                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...
415
                    $class = strtolower(str_replace('_', '-', $obj_class));
416
                    $class .= method_exists($obj_class, 'name') ? '-' . sanitize_title($object->name()) : '';
417
418
            }
419
        }
420
        return $prefix . $class . $suffix;
421
    }
422
423
424
425
    /**
426
     * EEH_Template::format_currency
427
     * This helper takes a raw float value and formats it according to the default config country currency settings, or
428
     * the country currency settings from the supplied country ISO code
429
     *
430
     * @param  float   $amount       raw money value
431
     * @param  boolean $return_raw   whether to return the formatted float value only with no currency sign or code
432
     * @param  boolean $display_code whether to display the country code (USD). Default = TRUE
433
     * @param string   $CNT_ISO      2 letter ISO code for a country
434
     * @param string   $cur_code_span_class
435
     * @return string        the html output for the formatted money value
436
     * @throws \EE_Error
437
     */
438
    public static function format_currency(
439
        $amount = null,
440
        $return_raw = false,
441
        $display_code = true,
442
        $CNT_ISO = '',
443
        $cur_code_span_class = 'currency-code'
444
    ) {
445
        // ensure amount was received
446
        if ($amount === null) {
447
            $msg = __('In order to format currency, an amount needs to be passed.', 'event_espresso');
448
            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
449
            return '';
450
        }
451
        //ensure amount is float
452
        $amount  = apply_filters('FHEE__EEH_Template__format_currency__raw_amount', (float)$amount);
453
        $CNT_ISO = apply_filters('FHEE__EEH_Template__format_currency__CNT_ISO', $CNT_ISO, $amount);
454
        // filter raw amount (allows 0.00 to be changed to "free" for example)
455
        $amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount', $amount, $return_raw);
456
        // still a number or was amount converted to a string like "free" ?
457
        if (is_float($amount_formatted)) {
458
            // was a country ISO code passed ? if so generate currency config object for that country
459
            $mny = $CNT_ISO !== '' ? new EE_Currency_Config($CNT_ISO) : null;
460
            // verify results
461 View Code Duplication
            if ( ! $mny instanceof EE_Currency_Config) {
462
                // set default config country currency settings
463
                $mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config
464
                    ? EE_Registry::instance()->CFG->currency
465
                    : new EE_Currency_Config();
466
            }
467
            // format float
468
            $amount_formatted = number_format($amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds);
469
            // add formatting ?
470
            if ( ! $return_raw) {
471
                // add currency sign
472
                if ($mny->sign_b4) {
473
                    if ($amount >= 0) {
474
                        $amount_formatted = $mny->sign . $amount_formatted;
475
                    } else {
476
                        $amount_formatted = '-' . $mny->sign . str_replace('-', '', $amount_formatted);
477
                    }
478
479
                } else {
480
                    $amount_formatted = $amount_formatted . $mny->sign;
481
                }
482
483
                // filter to allow global setting of display_code
484
                $display_code = apply_filters('FHEE__EEH_Template__format_currency__display_code', $display_code);
485
486
                // add currency code ?
487
                $amount_formatted = $display_code ? $amount_formatted . ' <span class="' . $cur_code_span_class . '">(' . $mny->code . ')</span>' : $amount_formatted;
488
            }
489
            // filter results
490
            $amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount_formatted',
491
                $amount_formatted, $mny, $return_raw);
492
        }
493
        // clean up vars
494
        unset($mny);
495
        // return formatted currency amount
496
        return $amount_formatted;
497
    }
498
499
500
    /**
501
     * This function is used for outputting the localized label for a given status id in the schema requested (and
502
     * possibly plural).  The intended use of this function is only for cases where wanting a label outside of a
503
     * related status model or model object (i.e. in documentation etc.)
504
     *
505
     * @param  string  $status_id Status ID matching a registered status in the esp_status table.  If there is no
506
     *                            match, then 'Unknown' will be returned.
507
     * @param  boolean $plural    Whether to return plural or not
508
     * @param  string  $schema    'UPPER', 'lower', or 'Sentence'
509
     * @return string             The localized label for the status id.
510
     */
511
    public static function pretty_status($status_id, $plural = false, $schema = 'upper')
512
    {
513
        /** @type EEM_Status $EEM_Status */
514
        $EEM_Status = EE_Registry::instance()->load_model('Status');
515
        $status     = $EEM_Status->localized_status(array($status_id => __('unknown', 'event_espresso')), $plural,
516
            $schema);
517
        return $status[$status_id];
518
    }
519
520
521
    /**
522
     * This helper just returns a button or link for the given parameters
523
     *
524
     * @param  string $url   the url for the link
525
     * @param  string $label What is the label you want displayed for the button
526
     * @param  string $class what class is used for the button (defaults to 'button-primary')
527
     * @param string  $icon
528
     * @param string  $title
529
     * @return string the html output for the button
530
     */
531
    public static function get_button_or_link($url, $label, $class = 'button-primary', $icon = '', $title = '')
532
    {
533
        $icon_html = '';
534
        if ( ! empty($icon)) {
535
            $dashicons = preg_split("(ee-icon |dashicons )", $icon);
536
            $dashicons = array_filter($dashicons);
537
            $count     = count($dashicons);
538
            $icon_html .= $count > 1 ? '<span class="ee-composite-dashicon">' : '';
539
            foreach ($dashicons as $dashicon) {
540
                $type = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
541
                $icon_html .= '<span class="' . $type . $dashicon . '"></span>';
542
            }
543
            $icon_html .= $count > 1 ? '</span>' : '';
544
        }
545
        $label  = ! empty($icon) ? $icon_html . $label : $label;
546
        $button = '<a id="' . sanitize_title_with_dashes($label) . '" href="' . $url . '" class="' . $class . '" title="' . $title . '">' . $label . '</a>';
547
        return $button;
548
    }
549
550
551
    /**
552
     * This returns a generated link that will load the related help tab on admin pages.
553
     *
554
     * @param  string     $help_tab_id the id for the connected help tab
555
     * @param bool|string $page        The page identifier for the page the help tab is on
556
     * @param bool|string $action      The action (route) for the admin page the help tab is on.
557
     * @param bool|string $icon_style  (optional) include css class for the style you want to use for the help icon.
558
     * @param bool|string $help_text   (optional) send help text you want to use for the link if default not to be used
559
     * @return string              generated link
560
     */
561
    public static function get_help_tab_link(
562
        $help_tab_id,
563
        $page = false,
564
        $action = false,
565
        $icon_style = false,
566
        $help_text = false
567
    ) {
568
569 View Code Duplication
        if ( ! $page) {
570
            $page = isset($_REQUEST['page']) && ! empty($_REQUEST['page']) ? sanitize_key($_REQUEST['page']) : $page;
571
        }
572
573 View Code Duplication
        if ( ! $action) {
574
            $action = isset($_REQUEST['action']) && ! empty($_REQUEST['action']) ? sanitize_key($_REQUEST['action']) : $action;
575
        }
576
577
        $action = empty($action) ? 'default' : $action;
578
579
580
        $help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
581
        $icon         = ! $icon_style ? ' dashicons-editor-help' : $icon_style;
582
        $help_text    = ! $help_text ? '' : $help_text;
583
        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.',
584
                'event_espresso') . '" > ' . $help_text . ' </a>';
585
    }
586
587
588
    /**
589
     * This helper generates the html structure for the jquery joyride plugin with the given params.
590
     *
591
     * @link http://zurb.com/playground/jquery-joyride-feature-tour-plugin
592
     * @see  EE_Admin_Page->_stop_callback() for the construct expected for the $stops param.
593
     * @param EE_Help_Tour
594
     * @return string         html
595
     */
596
    public static function help_tour_stops_generator(EE_Help_Tour $tour)
597
    {
598
        $id    = $tour->get_slug();
599
        $stops = $tour->get_stops();
600
601
        $content = '<ol style="display:none" id="' . $id . '">';
602
603
        foreach ($stops as $stop) {
604
            $data_id    = ! empty($stop['id']) ? ' data-id="' . $stop['id'] . '"' : '';
605
            $data_class = empty($data_id) && ! empty($stop['class']) ? ' data-class="' . $stop['class'] . '"' : '';
606
607
            //if container is set to modal then let's make sure we set the options accordingly
608
            if (empty($data_id) && empty($data_class)) {
609
                $stop['options']['modal']  = true;
610
                $stop['options']['expose'] = true;
611
            }
612
613
            $custom_class  = ! empty($stop['custom_class']) ? ' class="' . $stop['custom_class'] . '"' : '';
614
            $button_text   = ! empty($stop['button_text']) ? ' data-button="' . $stop['button_text'] . '"' : '';
615
            $inner_content = isset($stop['content']) ? $stop['content'] : '';
616
617
            //options
618
            if (isset($stop['options']) && is_array($stop['options'])) {
619
                $options = ' data-options="';
620
                foreach ($stop['options'] as $option => $value) {
621
                    $options .= $option . ':' . $value . ';';
622
                }
623
                $options .= '"';
624
            } else {
625
                $options = '';
626
            }
627
628
            //let's put all together
629
            $content .= '<li' . $data_id . $data_class . $custom_class . $button_text . $options . '>' . $inner_content . '</li>';
630
        }
631
632
        $content .= '</ol>';
633
        return $content;
634
    }
635
636
637
    /**
638
     * This is a helper method to generate a status legend for a given status array.
639
     * Note this will only work if the incoming statuses have a key in the EEM_Status->localized_status() methods
640
     * status_array.
641
     *
642
     * @param  array  $status_array  array of statuses that will make up the legend. In format:
643
     *                               array(
644
     *                               'status_item' => 'status_name'
645
     *                               )
646
     * @param  string $active_status This is used to indicate what the active status is IF that is to be highlighted in
647
     *                               the legend.
648
     * @throws EE_Error
649
     * @return string               html structure for status.
650
     */
651
    public static function status_legend($status_array, $active_status = '')
652
    {
653
        if ( ! is_array($status_array)) {
654
            throw new EE_Error(esc_html__('The EEH_Template::status_legend helper required the incoming status_array argument to be an array!',
655
                'event_espresso'));
656
        }
657
658
        $setup_array = array();
659
        foreach ($status_array as $item => $status) {
660
            $setup_array[$item] = array(
661
                'class'  => 'ee-status-legend ee-status-legend-' . $status,
662
                'desc'   => EEH_Template::pretty_status($status, false, 'sentence'),
663
                'status' => $status,
664
            );
665
        }
666
667
        $content = '<div class="ee-list-table-legend-container">' . "\n";
668
        $content .= '<h4 class="status-legend-title">' . esc_html__('Status Legend', 'event_espresso') . '</h4>' . "\n";
669
        $content .= '<dl class="ee-list-table-legend">' . "\n\t";
670
        foreach ($setup_array as $item => $details) {
671
            $active_class = $active_status == $details['status'] ? ' class="ee-is-active-status"' : '';
672
            $content .= '<dt id="ee-legend-item-tooltip-' . $item . '"' . $active_class . '>' . "\n\t\t";
673
            $content .= '<span class="' . $details['class'] . '"></span>' . "\n\t\t";
674
            $content .= '<span class="ee-legend-description">' . $details['desc'] . '</span>' . "\n\t";
675
            $content .= '</dt>' . "\n";
676
        }
677
        $content .= '</dl>' . "\n";
678
        $content .= '</div>' . "\n";
679
        return $content;
680
    }
681
682
683
    /**
684
     * Gets HTML for laying out a deeply-nested array (and objects) in a format
685
     * that's nice for presenting in the wp admin
686
     *
687
     * @param mixed $data
688
     * @return string
689
     */
690
    public static function layout_array_as_table($data)
691
    {
692
        if (is_object($data) || $data instanceof __PHP_Incomplete_Class) {
693
            $data = (array)$data;
694
        }
695
        ob_start();
696
        if (is_array($data)) {
697
            if (EEH_Array::is_associative_array($data)) {
698
                ?>
699
                <table class="widefat">
700
                    <tbody>
701
                    <?php
702
                    foreach ($data as $data_key => $data_values) {
703
                        ?>
704
                        <tr>
705
                            <td>
706
                                <?php echo $data_key; ?>
707
                            </td>
708
                            <td>
709
                                <?php echo self::layout_array_as_table($data_values); ?>
710
                            </td>
711
                        </tr>
712
                        <?php
713
                    } ?>
714
                    </tbody>
715
                </table>
716
                <?php
717
            } else {
718
                ?>
719
                <ul>
720
                    <?php
721
                    foreach ($data as $datum) {
722
                        echo "<li>";
723
                        echo self::layout_array_as_table($datum);
724
                        echo "</li>";
725
                    } ?>
726
                </ul>
727
                <?php
728
            }
729
        } else {
730
            //simple value
731
            echo esc_html($data);
732
        }
733
        return ob_get_clean();
734
    }
735
736
737
    /**
738
     * wrapper for self::get_paging_html() that simply echos the generated paging html
739
     *
740
     * @since 4.4.0
741
     * @see   self:get_paging_html() for argument docs.
742
     * @param        $total_items
743
     * @param        $current
744
     * @param        $per_page
745
     * @param        $url
746
     * @param bool   $show_num_field
747
     * @param string $paged_arg_name
748
     * @param array  $items_label
749
     * @return string
750
     */
751
    public static function paging_html(
752
        $total_items,
753
        $current,
754
        $per_page,
755
        $url,
756
        $show_num_field = true,
757
        $paged_arg_name = 'paged',
758
        $items_label = array()
759
    ) {
760
        echo self::get_paging_html($total_items, $current, $per_page, $url, $show_num_field, $paged_arg_name,
761
            $items_label);
762
    }
763
764
765
    /**
766
     * A method for generating paging similar to WP_List_Table
767
     *
768
     * @since    4.4.0
769
     * @see      wp-admin/includes/class-wp-list-table.php WP_List_Table::pagination()
770
     * @param  integer $total_items     How many total items there are to page.
771
     * @param  integer $current         What the current page is.
772
     * @param  integer $per_page        How many items per page.
773
     * @param  string  $url             What the base url for page links is.
774
     * @param  boolean $show_num_field  Whether to show the input for changing page number.
775
     * @param  string  $paged_arg_name  The name of the key for the paged query argument.
776
     * @param  array   $items_label     An array of singular/plural values for the items label:
777
     *                                  array(
778
     *                                  'single' => 'item',
779
     *                                  'plural' => 'items'
780
     *                                  )
781
     * @return  string
782
     */
783
    public static function get_paging_html(
784
        $total_items,
785
        $current,
786
        $per_page,
787
        $url,
788
        $show_num_field = true,
789
        $paged_arg_name = 'paged',
790
        $items_label = array()
791
    ) {
792
        $page_links     = array();
793
        $disable_first  = $disable_last = '';
794
        $total_items    = (int)$total_items;
795
        $per_page       = (int)$per_page;
796
        $current        = (int)$current;
797
        $paged_arg_name = empty($paged_arg_name) ? 'paged' : sanitize_key($paged_arg_name);
798
799
        //filter items_label
800
        $items_label = apply_filters(
801
            'FHEE__EEH_Template__get_paging_html__items_label',
802
            $items_label
803
        );
804
805
        if (empty($items_label)
806
            || ! is_array($items_label)
807
            || ! isset($items_label['single'])
808
            || ! isset($items_label['plural'])
809
        ) {
810
            $items_label = array(
811
                'single' => __('1 item', 'event_espresso'),
812
                'plural' => __('%s items', 'event_espresso'),
813
            );
814
        } else {
815
            $items_label = array(
816
                'single' => '1 ' . esc_html($items_label['single']),
817
                'plural' => '%s ' . esc_html($items_label['plural']),
818
            );
819
        }
820
821
        $total_pages = ceil($total_items / $per_page);
822
823
        if ($total_pages <= 1) {
824
            return '';
825
        }
826
827
        $item_label = $total_items > 1 ? sprintf($items_label['plural'], $total_items) : $items_label['single'];
828
829
        $output = '<span class="displaying-num">' . $item_label . '</span>';
830
831
        if ($current === 1) {
832
            $disable_first = ' disabled';
833
        }
834
        if ($current == $total_pages) {
835
            $disable_last = ' disabled';
836
        }
837
838
        $page_links[] = sprintf("<a class='%s' title='%s' href='%s'>%s</a>",
839
            'first-page' . $disable_first,
840
            esc_attr__('Go to the first page'),
841
            esc_url(remove_query_arg($paged_arg_name, $url)),
842
            '&laquo;'
843
        );
844
845
        $page_links[] = sprintf(
846
            '<a class="%s" title="%s" href="%s">%s</a>',
847
            'prev-page' . $disable_first,
848
            esc_attr__('Go to the previous page'),
849
            esc_url(add_query_arg($paged_arg_name, max(1, $current - 1), $url)),
850
            '&lsaquo;'
851
        );
852
853
        if ( ! $show_num_field) {
854
            $html_current_page = $current;
855
        } else {
856
            $html_current_page = sprintf("<input class='current-page' title='%s' type='text' name=$paged_arg_name value='%s' size='%d' />",
857
                esc_attr__('Current page'),
858
                $current,
859
                strlen($total_pages)
860
            );
861
        }
862
863
        $html_total_pages = sprintf(
864
            '<span class="total-pages">%s</span>',
865
            number_format_i18n($total_pages)
866
        );
867
        $page_links[]     = sprintf(
868
            _x('%3$s%1$s of %2$s%4$s', 'paging'),
869
            $html_current_page,
870
            $html_total_pages,
871
            '<span class="paging-input">',
872
            '</span>'
873
        );
874
875
        $page_links[] = sprintf(
876
            '<a class="%s" title="%s" href="%s">%s</a>',
877
            'next-page' . $disable_last,
878
            esc_attr__('Go to the next page'),
879
            esc_url(add_query_arg($paged_arg_name, min($total_pages, $current + 1), $url)),
880
            '&rsaquo;'
881
        );
882
883
        $page_links[] = sprintf(
884
            '<a class="%s" title="%s" href="%s">%s</a>',
885
            'last-page' . $disable_last,
886
            esc_attr__('Go to the last page'),
887
            esc_url(add_query_arg($paged_arg_name, $total_pages, $url)),
888
            '&raquo;'
889
        );
890
891
        $output .= "\n" . '<span class="pagination-links">' . join("\n", $page_links) . '</span>';
892
        // set page class
893
        if ($total_pages) {
894
            $page_class = $total_pages < 2 ? ' one-page' : '';
895
        } else {
896
            $page_class = ' no-pages';
897
        }
898
899
        return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
900
    }
901
902
903
    /**
904
     * @param string $wrap_class
905
     * @param string $wrap_id
906
     * @return string
907
     */
908
    public static function powered_by_event_espresso($wrap_class = '', $wrap_id = '', array $query_args = array())
909
    {
910
        $admin = is_admin() && ! (defined('DOING_AJAX') && DOING_AJAX);
911
        if (
912
            ! $admin &&
913
            ! apply_filters(
914
                'FHEE__EEH_Template__powered_by_event_espresso__show_reg_footer',
915
                EE_Registry::instance()->CFG->admin->show_reg_footer
916
            )
917
        ) {
918
            return '';
919
        }
920
        $tag        = $admin ? 'span' : 'div';
921
        $attributes = ! empty($wrap_id) ? " id=\"{$wrap_id}\"" : '';
922
        $wrap_class = $admin ? "{$wrap_class} float-left" : $wrap_class;
923
        $attributes .= ! empty($wrap_class)
924
            ? " class=\"{$wrap_class} powered-by-event-espresso-credit\""
925
            : ' class="powered-by-event-espresso-credit"';
926
        $query_args = array_merge(
927
            array(
928
                'ap_id'        => EE_Registry::instance()->CFG->admin->affiliate_id(),
929
                'utm_source'   => 'powered_by_event_espresso',
930
                'utm_medium'   => 'link',
931
                'utm_campaign' => 'powered_by',
932
            ),
933
            $query_args
934
        );
935
        $powered_by = apply_filters('FHEE__EEH_Template__powered_by_event_espresso_text',
936
            $admin ? 'Event Espresso - ' . EVENT_ESPRESSO_VERSION : 'Event Espresso');
937
        $url        = add_query_arg($query_args, 'https://eventespresso.com/');
938
        $url        = apply_filters('FHEE__EEH_Template__powered_by_event_espresso__url', $url);
939
        return (string)apply_filters(
940
            'FHEE__EEH_Template__powered_by_event_espresso__html',
941
            sprintf(
942
                esc_html_x(
943
                    '%3$s%1$sOnline event registration and ticketing powered by %2$s%3$s',
944
                    'Online event registration and ticketing powered by [link to eventespresso.com]',
945
                    'event_espresso'
946
                ),
947
                "<{$tag}{$attributes}>",
948
                "<a href=\"{$url}\" target=\"_blank\" rel=\"nofollow\">{$powered_by}</a></{$tag}>",
949
                $admin ? '' : '<br />'
950
            ),
951
            $wrap_class,
952
            $wrap_id
953
        );
954
    }
955
956
957
} //end EEH_Template class
958
959
960
961
962 View Code Duplication
if ( ! function_exists('espresso_pagination')) {
963
    /**
964
     *    espresso_pagination
965
     *
966
     * @access    public
967
     * @return    void
968
     */
969
    function espresso_pagination()
970
    {
971
        global $wp_query;
972
        $big        = 999999999; // need an unlikely integer
973
        $pagination = paginate_links(
974
            array(
975
                'base'         => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
976
                'format'       => '?paged=%#%',
977
                'current'      => max(1, get_query_var('paged')),
978
                'total'        => $wp_query->max_num_pages,
979
                'show_all'     => true,
980
                'end_size'     => 10,
981
                'mid_size'     => 6,
982
                'prev_next'    => true,
983
                'prev_text'    => __('&lsaquo; PREV', 'event_espresso'),
984
                'next_text'    => __('NEXT &rsaquo;', 'event_espresso'),
985
                'type'         => 'plain',
986
                'add_args'     => false,
987
                'add_fragment' => '',
988
            )
989
        );
990
        echo ! empty($pagination) ? '<div class="ee-pagination-dv clear">' . $pagination . '</div>' : '';
991
    }
992
}