Completed
Branch BUG-10381-asset-loading (0f96c1)
by
unknown
60:43 queued 48:13
created

ShortcodesManager::getHeader()   B

Complexity

Conditions 6
Paths 13

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 13
c 1
b 0
f 0
nc 13
nop 0
dl 0
loc 20
rs 8.8571
1
<?php
2
namespace EventEspresso\core\services\shortcodes;
3
4
use EventEspresso\core\domain\EnqueueAssetsInterface;
5
// use EventEspresso\core\domain\SetHooksInterface;
6
use EventEspresso\core\exceptions\InvalidClassException;
7
use EventEspresso\core\exceptions\InvalidDataTypeException;
8
use EventEspresso\core\exceptions\InvalidEntityException;
9
use EventEspresso\core\exceptions\InvalidFilePathException;
10
use EventEspresso\core\exceptions\InvalidIdentifierException;
11
use EventEspresso\core\exceptions\InvalidInterfaceException;
12
use EventEspresso\core\services\collections\CollectionDetails;
13
use EventEspresso\core\services\collections\CollectionInterface;
14
use EventEspresso\core\services\collections\CollectionLoader;
15
16
defined('EVENT_ESPRESSO_VERSION') || exit;
17
18
19
20
/**
21
 * Class ShortcodesManager
22
 * Loads a Collection of ShortcodeInterface classes
23
 * then retrieves shortcode tags and calls add_shortcode() for each
24
 * ensures assets are registered and enqueued at the appropriate time
25
 *
26
 * @package       Event Espresso
27
 * @author        Brent Christensen
28
 * @since         4.9.26
29
 */
30
class ShortcodesManager
31
{
32
33
    /**
34
     * @var LegacyShortcodesManager $LegacyShortcodesManager
35
     */
36
    private $LegacyShortcodesManager;
37
38
    /**
39
     * @var ShortcodeInterface[] $shortcodes
40
     */
41
    private $shortcodes;
42
43
44
45
    /**
46
     * ShortcodesManager constructor
47
     *
48
     * @param LegacyShortcodesManager $LegacyShortcodesManager
49
     */
50
    public function __construct(LegacyShortcodesManager $LegacyShortcodesManager) {
51
        $this->LegacyShortcodesManager = $LegacyShortcodesManager;
52
        // assemble a list of installed and active shortcodes
53
        add_action(
54
            'AHEE__EE_System__register_shortcodes_modules_and_widgets',
55
            array($this, 'registerShortcodes'),
56
            999
57
        );
58
        //  call add_shortcode() for all installed shortcodes
59
        add_action('AHEE__EE_System__core_loaded_and_ready', array($this, 'addShortcodes'));
60
        // check content for shortcodes, the old way, and the more efficient new way
61
        add_action('parse_query', array($this->LegacyShortcodesManager, 'initializeShortcodes'), 5);
62
        add_action('get_header', array($this, 'getHeader'));
63
    }
64
65
66
67
    /**
68
     * @return CollectionInterface|ShortcodeInterface[]
69
     * @throws InvalidIdentifierException
70
     * @throws InvalidInterfaceException
71
     * @throws InvalidFilePathException
72
     * @throws InvalidEntityException
73
     * @throws InvalidDataTypeException
74
     * @throws InvalidClassException
75
     */
76
    public function getShortcodes()
77
    {
78
        if ( ! $this->shortcodes instanceof CollectionInterface) {
79
            $this->shortcodes = $this->loadShortcodesCollection();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->loadShortcodesCollection() can also be of type object<EventEspresso\cor...ns\CollectionInterface>. However, the property $shortcodes is declared as type array<integer,object<Eve...es\ShortcodeInterface>>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
80
        }
81
        return $this->shortcodes;
82
    }
83
84
85
86
    /**
87
     * @return CollectionInterface|ShortcodeInterface[]
88
     * @throws InvalidIdentifierException
89
     * @throws InvalidInterfaceException
90
     * @throws InvalidFilePathException
91
     * @throws InvalidEntityException
92
     * @throws InvalidDataTypeException
93
     * @throws InvalidClassException
94
     */
95
    protected function loadShortcodesCollection()
96
    {
97
        $loader = new CollectionLoader(
98
            new CollectionDetails(
99
            // collection name
100
                'shortcodes',
101
                // collection interface
102
                '\EventEspresso\core\services\shortcodes\ShortcodeInterface',
103
                // FQCNs for classes to add (all classes within that namespace will be loaded)
104
                array('EventEspresso\core\domain\entities\shortcodes'),
105
                // filepaths to classes to add
106
                array(),
107
                // filemask to use if parsing folder for files to add
108
                '',
109
                // what to use as identifier for collection entities
110
                // using CLASS NAME prevents duplicates (works like a singleton)
111
                CollectionDetails::ID_CLASS_NAME
112
            )
113
        );
114
        return $loader->getCollection();
115
    }
116
117
118
119
    /**
120
     * @return void
121
     * @throws InvalidInterfaceException
122
     * @throws InvalidIdentifierException
123
     * @throws InvalidFilePathException
124
     * @throws InvalidEntityException
125
     * @throws InvalidDataTypeException
126
     * @throws InvalidClassException
127
     */
128
    public function registerShortcodes()
129
    {
130
        $this->shortcodes = apply_filters(
131
            'FHEE__EventEspresso_core_services_shortcodes_ShortcodesManager__registerShortcodes__shortcode_collection',
132
            $this->getShortcodes()
133
        );
134
        $this->LegacyShortcodesManager->registerShortcodes();
135
    }
136
137
138
139
    /**
140
     * @return void
141
     */
142
    public function addShortcodes()
143
    {
144
        // cycle thru shortcode folders
145
        foreach ($this->shortcodes as $shortcode) {
146
            /** @var ShortcodeInterface $shortcode */
147
            if ( $shortcode instanceof EnqueueAssetsInterface) {
148
                add_action('wp_enqueue_scripts', array($shortcode, 'registerScriptsAndStylesheets'), 10);
149
                add_action('wp_enqueue_scripts', array($shortcode, 'enqueueStylesheets'), 11);
150
            }
151
            // add_shortcode() if it has not already been added
152
            if ( ! shortcode_exists($shortcode->getTag())) {
153
                add_shortcode($shortcode->getTag(), array($shortcode, 'processShortcodeCallback'));
154
            }
155
        }
156
        $this->LegacyShortcodesManager->addShortcodes();
157
    }
158
159
160
161
    /**
162
     * callback for the WP "get_header" hook point
163
     * checks posts for EE shortcodes, and initializes them,
164
     * then toggles filter switch that loads core default assets
165
     *
166
     * @return void
167
     */
168
    public function getHeader()
169
    {
170
        global $wp_query;
171
        if (empty($wp_query->posts)) {
172
            return;
173
        }
174
        $load_assets = false;
175
        // array of posts displayed in current request
176
        $posts = is_array($wp_query->posts) ? $wp_query->posts : array($wp_query->posts);
177
        foreach ($posts as $post) {
178
            // now check post content and excerpt for EE shortcodes
179
            $load_assets = $this->parseContentForShortcodes($post->post_content)
180
                ? true
181
                : $load_assets;
182
        }
183
        if ($load_assets) {
184
            add_filter('FHEE_load_css', '__return_true');
185
            add_filter('FHEE_load_js', '__return_true');
186
        }
187
    }
188
189
190
191
    /**
192
     * checks supplied content against list of shortcodes,
193
     * then initializes any found shortcodes, and returns true.
194
     * returns false if no shortcodes found.
195
     *
196
     * @param string $content
197
     * @return bool
198
     */
199
    public function parseContentForShortcodes($content)
200
    {
201
        $has_shortcode = false;
202
        foreach ($this->shortcodes as $shortcode) {
203
            /** @var ShortcodeInterface $shortcode */
204
            if (has_shortcode($content, $shortcode->getTag())) {
205
                $shortcode->initializeShortcode();
206
                $has_shortcode = true;
207
            }
208
        }
209
        return $has_shortcode;
210
    }
211
212
}
213
// End of file ShortcodesManager.php
214
// Location: EventEspresso\core\services\shortcodes/ShortcodesManager.php