Completed
Branch BUG-10626-dst-unit-test (1e1790)
by
unknown
45:29 queued 34:12
created

EspressoShortcode::initialized()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
namespace EventEspresso\core\services\shortcodes;
3
4
use EE_Error;
5
use EE_Event;
6
use EEH_Event_View;
7
use EventEspresso\core\domain\EnqueueAssetsInterface;
8
use EventEspresso\core\services\cache\PostRelatedCacheManager;
9
use WP_Post;
10
11
defined('EVENT_ESPRESSO_VERSION') || exit;
12
13
14
15
/**
16
 * Class EspressoShortcode
17
 * base class for all EE shortcode classes
18
 *
19
 * @package       Event Espresso
20
 * @author        Brent Christensen
21
 * @since         $VID:$
22
 */
23
abstract class EspressoShortcode implements ShortcodeInterface
24
{
25
26
    /**
27
     * transient prefix
28
     *
29
     * @type string
30
     */
31
    const CACHE_TRANSIENT_PREFIX = 'ee_sc_';
32
33
    /**
34
     * @var PostRelatedCacheManager $cache_manager
35
     */
36
    private $cache_manager;
37
38
    /**
39
     * true if ShortcodeInterface::initializeShortcode() has been called
40
     * if false, then that will get called before processing
41
     *
42
     * @var boolean $initialized
43
     */
44
    private $initialized = false;
45
46
47
48
    /**
49
     * EspressoShortcode constructor
50
     *
51
     * @param PostRelatedCacheManager $cache_manager
52
     */
53
    public function __construct(PostRelatedCacheManager $cache_manager)
54
    {
55
        $this->cache_manager = $cache_manager;
56
    }
57
58
59
60
    /**
61
     * @return void
62
     */
63
    public function shortcodeHasBeenInitialized()
64
    {
65
        $this->initialized = true;
66
    }
67
68
69
70
    /**
71
     * enqueues scripts then processes the shortcode
72
     *
73
     * @param array $attributes
74
     * @return string
75
     * @throws EE_Error
76
     */
77
    final public function processShortcodeCallback($attributes = array())
78
    {
79
        if ($this instanceof EnqueueAssetsInterface) {
80
            if (is_admin()) {
81
                $this->enqueueAdminScripts();
82
            } else {
83
                $this->enqueueScripts();
84
            }
85
        }
86
        return $this->shortcodeContent(
87
            $this->sanitizeAttributes((array)$attributes)
88
        );
89
    }
90
91
92
93
    /**
94
     * If shortcode caching is enabled for the shortcode,
95
     * and cached results exist, then that will be returned
96
     * else new content will be generated.
97
     * If caching is enabled, then the new content will be cached for later.
98
     *
99
     * @param array $attributes
100
     * @return mixed|string
101
     * @throws EE_Error
102
     */
103
    private function shortcodeContent(array $attributes)
104
    {
105
        $shortcode = $this;
106
        $post_ID = $this->currentPostID();
107
        // something like "SC_EVENTS-123"
108
        $cache_ID = $this->shortcodeCacheID($post_ID);
109
        $this->cache_manager->clearPostRelatedCacheOnUpdate($post_ID, $cache_ID);
110
        return $this->cache_manager->get(
111
            $cache_ID,
112
            // serialized attributes
113
            wp_json_encode($attributes),
114
            // Closure for generating content if cache is expired
115
            function () use ($shortcode, $attributes) {
116
                if($shortcode->initialized() === false){
117
                    $shortcode->initializeShortcode();
118
                }
119
                return $shortcode->processShortcode($attributes);
120
            },
121
            // filterable cache expiration set by each shortcode
122
            apply_filters(
123
                'FHEE__EventEspresso_core_services_shortcodes_EspressoShortcode__shortcodeContent__cache_expiration',
124
                $this->cacheExpiration(),
125
                $this->getTag(),
126
                $this
127
            )
128
        );
129
    }
130
131
132
133
    /**
134
     * @return int
135
     * @throws EE_Error
136
     */
137
    private function currentPostID()
138
    {
139
        // try to get EE_Event any way we can
140
        $event = EEH_Event_View::get_event();
141
        // then get some kind of ID
142
        if ($event instanceof EE_Event) {
143
            return $event->ID();
144
        }
145
        global $post;
146
        if ($post instanceof WP_Post) {
0 ignored issues
show
Bug introduced by
The class WP_Post does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
147
            return $post->ID;
148
        }
149
        return 0;
150
    }
151
152
153
154
    /**
155
     * @param int $post_ID
156
     * @return string
157
     * @throws EE_Error
158
     */
159
    private function shortcodeCacheID($post_ID)
160
    {
161
        $tag = str_replace('ESPRESSO_', '', $this->getTag());
162
        return "SC_{$tag}-{$post_ID}";
163
    }
164
165
166
167
    /**
168
     * array for defining custom attribute sanitization callbacks,
169
     * where keys match keys in your attributes array,
170
     * and values represent the sanitization function you wish to be applied to that attribute.
171
     * So for example, if you had an integer attribute named "event_id"
172
     * that you wanted to be sanitized using absint(),
173
     * then you would return the following:
174
     *      array('event_id' => 'absint')
175
     * Entering 'skip_sanitization' for the callback value
176
     * means that no sanitization will be applied
177
     * on the assumption that the attribute
178
     * will be sanitized at some point... right?
179
     * You wouldn't pass around unsanitized attributes would you?
180
     * That would be very Tom Foolery of you!!!
181
     *
182
     * @return array
183
     */
184
    protected function customAttributeSanitizationMap()
185
    {
186
        return array();
187
    }
188
189
190
191
    /**
192
     * Performs basic sanitization on shortcode attributes
193
     * Since incoming attributes from the shortcode usage in the WP editor will all be strings,
194
     * most attributes will by default be sanitized using the sanitize_text_field() function.
195
     * This can be overridden using the customAttributeSanitizationMap() method (see above),
196
     * all other attributes would be sanitized using the defaults in the switch statement below
197
     *
198
     * @param array $attributes
199
     * @return array
200
     */
201
    private function sanitizeAttributes(array $attributes)
202
    {
203
        $custom_sanitization = $this->customAttributeSanitizationMap();
204 View Code Duplication
        foreach ($attributes as $key => $value) {
205
            // is a custom sanitization callback specified ?
206
            if (isset($custom_sanitization[$key])) {
207
                $callback = $custom_sanitization[$key];
208
                if ($callback === 'skip_sanitization') {
209
                    $attributes[$key] = $value;
210
                    continue;
211
                }
212
                if (function_exists($callback)) {
213
                    $attributes[$key] = $callback($value);
214
                    continue;
215
                }
216
            }
217
            switch (true) {
218
                case $value === null :
219
                case is_int($value) :
220
                case is_float($value) :
221
                    // typical booleans
222
                case in_array($value, array(true, 'true', '1', 'on', 'yes', false, 'false', '0', 'off', 'no'), true) :
223
                    $attributes[$key] = $value;
224
                    break;
225
                case is_string($value) :
226
                    $attributes[$key] = sanitize_text_field($value);
227
                    break;
228
                case is_array($value) :
229
                    $attributes[$key] = $this->sanitizeAttributes($value);
230
                    break;
231
                default :
232
                    // only remaining data types are Object and Resource
233
                    // which are not allowed as shortcode attributes
234
                    $attributes[$key] = null;
235
                    break;
236
            }
237
        }
238
        return $attributes;
239
    }
240
241
242
243
    /**
244
     * Returns whether or not this shortcode has been initialized
245
     * @return boolean
246
     */
247
    public function initialized(){
248
        return $this->initialized;
249
    }
250
251
252
253
}
254
// End of file EspressoShortcode.php
255
// Location: EventEspresso\core\services\shortcodes/EspressoShortcode.php
256