GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

contentBlueprintsEvents::__formAction()   F
last analyzed

Complexity

Conditions 32
Paths > 20000

Size

Total Lines 261
Code Lines 116

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 32
eloc 116
c 3
b 0
f 0
nc 100800
nop 0
dl 0
loc 261
rs 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @package content
4
 */
5
6
/**
7
 * The Event Editor allows a developer to create events that typically
8
 * allow Frontend forms to populate Sections or edit Entries.
9
 */
10
11
class contentBlueprintsEvents extends ResourcesPage
0 ignored issues
show
Coding Style introduced by
This class is not in CamelCase format.

Classes in PHP are usually named in CamelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. The whole name starts with a capital letter as well.

Thus the name database provider becomes DatabaseProvider.

Loading history...
12
{
13
    public $_errors = array();
14
15
    public function __viewIndex($resource_type)
16
    {
17
        parent::__viewIndex(ResourceManager::RESOURCE_TYPE_EVENT);
18
19
        $this->setTitle(__('%1$s &ndash; %2$s', array(__('Events'), __('Symphony'))));
20
        $this->appendSubheading(__('Events'), Widget::Anchor(__('Create New'), Administration::instance()->getCurrentPageURL().'new/', __('Create a new event'), 'create button', null, array('accesskey' => 'c')));
21
    }
22
23
    public function __viewNew()
24
    {
25
        $this->__form();
26
    }
27
28
    public function __viewEdit()
29
    {
30
        $this->__form();
31
    }
32
33
    public function __viewInfo()
34
    {
35
        $this->__form(true);
36
    }
37
38
    public function __form($readonly = false)
0 ignored issues
show
Coding Style introduced by
Incorrect spacing between argument "$readonly" and equals sign; expected 0 but found 1
Loading history...
Coding Style introduced by
Incorrect spacing between default value and equals sign for argument "$readonly"; expected 0 but found 1
Loading history...
39
    {
40
        $formHasErrors = (is_array($this->_errors) && !empty($this->_errors));
41
42
        if ($formHasErrors) {
43
            $this->pageAlert(
44
                __('An error occurred while processing this form. See below for details.'),
45
                Alert::ERROR
46
            );
47
48
            // These alerts are only valid if the form doesn't have errors
49
        } elseif (isset($this->_context[2])) {
50
            $time = Widget::Time();
51
52
            switch ($this->_context[2]) {
53
                case 'saved':
54
                    $message = __('Event updated at %s.', array($time->generate()));
55
                    break;
56
                case 'created':
57
                    $message = __('Event created at %s.', array($time->generate()));
58
            }
59
60
            $this->pageAlert(
61
                $message
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $message does not seem to be defined for all execution paths leading up to this point.
Loading history...
62
                . ' <a href="' . SYMPHONY_URL . '/blueprints/events/new/" accesskey="c">'
0 ignored issues
show
Bug introduced by
The constant SYMPHONY_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
63
                . __('Create another?')
64
                . '</a> <a href="' . SYMPHONY_URL . '/blueprints/events/" accesskey="a">'
65
                . __('View all Events')
66
                . '</a>',
67
                Alert::SUCCESS
68
            );
69
        }
70
71
        $isEditing = ($readonly ? true : false);
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
72
        $fields = array('name' => null, 'filters' => null);
73
        $about = array('name' => null);
74
        $providers = Symphony::ExtensionManager()->getProvidersOf(iProvider::EVENT);
75
        $canonical_link = null;
76
77
        if (isset($_POST['fields'])) {
78
            $fields = $_POST['fields'];
79
80
            if ($this->_context[0] == 'edit') {
81
                $isEditing = true;
82
            }
83
        } elseif ($this->_context[0] == 'edit' || $this->_context[0] == 'info') {
84
            $isEditing = true;
85
            $handle = $this->_context[1];
86
            $existing = EventManager::create($handle);
87
            $about = General::array_map_recursive('stripslashes', $existing->about());
0 ignored issues
show
Bug introduced by
The method about() does not exist on Event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

87
            $about = General::array_map_recursive('stripslashes', $existing->/** @scrutinizer ignore-call */ about());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
88
89
            if ($this->_context[0] == 'edit' && !$existing->allowEditorToParse()) {
0 ignored issues
show
Bug introduced by
The method allowEditorToParse() does not exist on Event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

89
            if ($this->_context[0] == 'edit' && !$existing->/** @scrutinizer ignore-call */ allowEditorToParse()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
90
                redirect(SYMPHONY_URL . '/blueprints/events/info/' . $handle . '/');
91
            }
92
93
            $fields['name'] = $about['name'];
94
            $fields['source'] = stripslashes($existing->getSource());
0 ignored issues
show
Bug introduced by
The method getSource() does not exist on Event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

94
            $fields['source'] = stripslashes($existing->/** @scrutinizer ignore-call */ getSource());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
95
            $provided = false;
96
97
            if (!empty($providers)) {
98
                foreach ($providers as $providerClass => $provider) {
99
                    if ($fields['source'] == call_user_func(array($providerClass, 'getClass'))) {
100
                        $fields = array_merge($fields, $existing->settings());
0 ignored issues
show
Bug introduced by
The method settings() does not exist on Event. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

100
                        $fields = array_merge($fields, $existing->/** @scrutinizer ignore-call */ settings());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
101
                        $provided = true;
102
                        break;
103
                    }
104
                }
105
            }
106
107
            if (!$provided) {
108
                if (isset($existing->eParamFILTERS)) {
109
                    $fields['filters'] = array_map('stripslashes', $existing->eParamFILTERS);
110
                }
111
            }
112
113
            $canonical_link = '/blueprints/events/' . $this->_context[0] . '/' . $handle . '/';
114
        }
115
116
        $name = null;
117
        // Handle name on edited changes, or from reading an edited datasource
118
        if (isset($about['name'])) {
119
            $name = $about['name'];
120
        } elseif (isset($fields['name'])) {
121
            $name = $fields['name'];
122
        }
123
124
        $this->setPageType('form');
125
        $this->setTitle(__(($isEditing ? '%1$s &ndash; %2$s &ndash; %3$s' : '%2$s &ndash; %3$s'), array($name, __('Events'), __('Symphony'))));
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
126
        if ($canonical_link) {
127
            $this->addElementToHead(new XMLElement('link', null, array(
128
                'rel' => 'canonical',
129
                'href' => SYMPHONY_URL . $canonical_link,
130
            )));
131
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
132
        $this->appendSubheading(($isEditing ? $about['name'] : __('Untitled')));
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
133
        $this->insertBreadcrumbs(array(
134
            Widget::Anchor(__('Events'), SYMPHONY_URL . '/blueprints/events/'),
135
        ));
136
137
        if (!$readonly) {
138
            $fieldset = new XMLElement('fieldset');
139
            $fieldset->setAttribute('class', 'settings');
140
            $fieldset->appendChild(new XMLElement('legend', __('Essentials')));
141
142
            // Target
143
            $sources = new XMLElement('div', null, array('class' => 'apply actions'));
144
            $div = new XMLElement('div');
145
            $label = Widget::Label(__('Target'), null, 'apply-label-left');
146
            $sources->appendChild($label);
147
            $sources->appendChild($div);
148
149
            $sections = SectionManager::fetch(null, 'ASC', 'name');
150
            $options = array();
151
            $section_options = array();
152
            $source = isset($fields['source']) ? $fields['source'] : null;
153
154
            if (is_array($sections) && !empty($sections)) {
155
                $section_options = array('label' => __('Sections'), 'options' => array());
156
157
                foreach ($sections as $s) {
158
                    $section_options['options'][] = array($s->get('id'), $source == $s->get('id'), General::sanitize($s->get('name')));
159
                }
160
            }
161
162
            $options[] = $section_options;
163
164
            // Loop over the event providers
165
            if (!empty($providers)) {
166
                $p = array('label' => __('From extensions'), 'options' => array());
167
168
                foreach ($providers as $providerClass => $provider) {
169
                    $p['options'][] = array(
170
                        $providerClass, ($fields['source'] == $providerClass), $provider
171
                    );
172
                }
173
174
                $options[] = $p;
175
            }
176
177
            $div->appendChild(
178
                Widget::Select('source', $options, array('id' => 'event-context'))
179
            );
180
181
            if (isset($this->_errors['source'])) {
182
                $this->Context->prependChild(Widget::Error($sources, $this->_errors['source']));
183
            } else {
184
                $this->Context->prependChild($sources);
185
            }
186
187
            $this->Form->appendChild(
188
                Widget::Input('fields[source]', $options[0]['options'][0][0], 'hidden', array('id' => 'event-source'))
189
            );
190
191
            // Name
192
            $group = new XMLElement('div');
193
            $label = Widget::Label(__('Name'));
194
            $label->appendChild(Widget::Input('fields[name]', General::sanitize($fields['name'])));
195
196
            $div = new XMLElement('div');
197
            $div->setAttribute('class', 'column');
198
199
            if (isset($this->_errors['name'])) {
200
                $div->appendChild(Widget::Error($label, $this->_errors['name']));
201
            } else {
202
                $div->appendChild($label);
203
            }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
204
            $group->appendChild($div);
205
            $fieldset->appendChild($group);
206
            $this->Form->appendChild($fieldset);
207
208
            // Filters
209
            $fieldset = new XMLElement('fieldset');
210
            $fieldset->setAttribute('class', 'settings pickable');
211
            $fieldset->appendChild(new XMLElement('legend', __('Filters')));
212
            $p = new XMLElement('p', __('Event Filters add additional conditions or actions to an event.'));
213
            $p->setAttribute('class', 'help');
214
            $fieldset->appendChild($p);
215
216
            $filters = isset($fields['filters']) ? $fields['filters'] : array();
217
            $options = array(
218
                array('admin-only', in_array('admin-only', $filters), __('Admin Only')),
219
                array('send-email', in_array('send-email', $filters), __('Send Notification Email')),
220
                array('expect-multiple', in_array('expect-multiple', $filters), __('Allow Multiple')),
221
            );
222
223
            /**
224
             * Allows adding of new filter rules to the Event filter rule select box
225
             *
226
             * @delegate AppendEventFilter
227
             * @param string $context
228
             * '/blueprints/events/(edit|new|info)/'
229
             * @param array $selected
230
             *  An array of all the selected filters for this Event
231
             * @param array $options
232
             *  An array of all the filters that are available, passed by reference
233
             */
234
            Symphony::ExtensionManager()->notifyMembers('AppendEventFilter', '/blueprints/events/' . $this->_context[0] . '/', array(
235
                'selected' => $filters,
236
                'options' => &$options
237
            ));
238
239
            $fieldset->appendChild(Widget::Select('fields[filters][]', $options, array('multiple' => 'multiple', 'id' => 'event-filters')));
240
            $this->Form->appendChild($fieldset);
241
242
            // Connections
243
            $fieldset = new XMLElement('fieldset');
244
            $fieldset->setAttribute('class', 'settings');
245
            $fieldset->appendChild(new XMLElement('legend', __('Attach to Pages')));
246
            $p = new XMLElement('p', __('The event will only be available on the selected pages.'));
247
            $p->setAttribute('class', 'help');
248
            $fieldset->appendChild($p);
249
250
            $div = new XMLElement('div');
251
            $label = Widget::Label(__('Pages'));
252
253
            $pages = PageManager::fetch();
254
            $event_handle = str_replace('-', '_', Lang::createHandle($fields['name']));
255
            $connections = ResourceManager::getAttachedPages(ResourceManager::RESOURCE_TYPE_EVENT, $event_handle);
256
            $selected = array();
257
258
            foreach ($connections as $connection) {
259
                $selected[] = $connection['id'];
260
            }
261
262
            $options = array();
263
264
            foreach ($pages as $page) {
265
                $options[] = array(
266
                    $page['id'],
267
                    in_array($page['id'], $selected),
268
                    General::sanitize(PageManager::resolvePageTitle($page['id']))
269
                );
270
            }
271
272
            $label->appendChild(Widget::Select('fields[connections][]', $options, array('multiple' => 'multiple')));
273
            $div->appendChild($label);
274
275
            $fieldset->appendChild($div);
276
            $this->Form->appendChild($fieldset);
277
278
            // Providers
279
            if (!empty($providers)) {
280
                foreach ($providers as $providerClass => $provider) {
281
                    if ($isEditing && $fields['source'] !== call_user_func(array($providerClass, 'getSource'))) {
282
                        continue;
283
                    }
284
285
                    call_user_func_array(array($providerClass, 'buildEditor'), array($this->Form, &$this->_errors, $fields, $handle));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $handle does not seem to be defined for all execution paths leading up to this point.
Loading history...
286
                }
287
            }
288
        } else {
289
            // Author
290
            if (isset($about['author']['website'])) {
291
                $link = Widget::Anchor($about['author']['name'], General::validateURL($about['author']['website']));
292
            } elseif (isset($about['author']['email'])) {
293
                $link = Widget::Anchor($about['author']['name'], 'mailto:' . $about['author']['email']);
294
            } else {
295
                $link = $about['author']['name'];
296
            }
297
298
            if ($link) {
299
                $fieldset = new XMLElement('fieldset');
300
                $fieldset->setAttribute('class', 'settings');
301
                $fieldset->appendChild(new XMLElement('legend', __('Author')));
302
                $fieldset->appendChild(new XMLElement('p', $link->generate(false)));
303
                $this->Form->appendChild($fieldset);
304
            }
305
306
            // Version
307
            $fieldset = new XMLElement('fieldset');
308
            $fieldset->setAttribute('class', 'settings');
309
            $fieldset->appendChild(new XMLElement('legend', __('Version')));
310
            $version = array_key_exists('version', $about) ? $about['version'] : null;
311
            $release_date = array_key_exists('release-date', $about) ? $about['release-date'] : filemtime(EventManager::__getDriverPath($handle));
312
313
            if (preg_match('/^\d+(\.\d+)*$/', $version)) {
314
                $fieldset->appendChild(
315
                    new XMLElement('p', __('%1$s released on %2$s', array($version, DateTimeObj::format($release_date, __SYM_DATE_FORMAT__))))
0 ignored issues
show
Bug introduced by
The constant __SYM_DATE_FORMAT__ was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
316
                );
317
            } elseif (!is_null($version)) {
318
                $fieldset->appendChild(
319
                    new XMLElement('p', __('Created by %1$s at %2$s', array($version, DateTimeObj::format($release_date, __SYM_DATE_FORMAT__))))
320
                );
321
            } else {
322
                $fieldset->appendChild(
323
                    new XMLElement('p', __('Last modified on %s', array(DateTimeObj::format($release_date, __SYM_DATE_FORMAT__))))
324
                );
325
            }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
326
            $this->Form->appendChild($fieldset);
327
        }
328
329
        // If we are editing an event, it assumed that the event has documentation
330
        $fieldset = new XMLElement('fieldset');
331
        $fieldset->setAttribute('id', 'event-documentation');
332
        $fieldset->setAttribute('class', 'settings');
333
334
        if ($isEditing && method_exists($existing, 'documentation')) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $existing does not seem to be defined for all execution paths leading up to this point.
Loading history...
335
            $doc = $existing->documentation();
336
337
            if ($doc) {
338
                $fieldset->setValue(
339
                    '<legend>' . __('Documentation') . '</legend>' . PHP_EOL .
340
                    General::tabsToSpaces(is_object($doc) ? $doc->generate(true, 4) : $doc)
341
                );
342
            }
343
        }
344
345
        $this->Form->appendChild($fieldset);
346
347
        $div = new XMLElement('div');
348
        $div->setAttribute('class', 'actions');
349
        $div->appendChild(Widget::Input('action[save]', ($isEditing ? __('Save Changes') : __('Create Event')), 'submit', array('accesskey' => 's')));
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
350
351
        if ($isEditing) {
352
            $button = new XMLElement('button', __('Delete'));
353
            $button->setAttributeArray(array('name' => 'action[delete]', 'class' => 'button confirm delete', 'title' => __('Delete this event'), 'type' => 'submit', 'accesskey' => 'd', 'data-message' => __('Are you sure you want to delete this event?')));
354
            $div->appendChild($button);
355
        }
356
357
        if (!$readonly) {
358
            $this->Form->appendChild($div);
359
        }
360
    }
361
362
    public function __actionNew()
363
    {
364
        if (array_key_exists('save', $_POST['action'])) {
365
            return $this->__formAction();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->__formAction() targeting contentBlueprintsEvents::__formAction() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
366
        }
367
    }
368
369
    public function __actionEdit()
370
    {
371
        if (array_key_exists('save', $_POST['action'])) {
372
            return $this->__formAction();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->__formAction() targeting contentBlueprintsEvents::__formAction() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
373
        } elseif (array_key_exists('delete', $_POST['action'])) {
374
            /**
375
             * Prior to deleting the Event file. Target file path is provided.
376
             *
377
             * @delegate EventPreDelete
378
             * @since Symphony 2.2
379
             * @param string $context
380
             * '/blueprints/events/'
381
             * @param string $file
382
             *  The path to the Event file
383
             */
384
            Symphony::ExtensionManager()->notifyMembers('EventPreDelete', '/blueprints/events/', array('file' => EVENTS . "/event." . $this->_context[1] . ".php"));
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal /event. does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Coding Style Comprehensibility introduced by
The string literal .php does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
Bug introduced by
The constant EVENTS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
385
386
            if (!General::deleteFile(EVENTS . '/event.' . $this->_context[1] . '.php')) {
387
                $this->pageAlert(
388
                    __('Failed to delete %s.', array('<code>' . $this->_context[1] . '</code>'))
389
                    . ' ' . __('Please check permissions on %s.', array('<code>/workspace/events</code>')),
390
                    Alert::ERROR
391
                );
392
            } else {
393
                $pages = ResourceManager::getAttachedPages(ResourceManager::RESOURCE_TYPE_EVENT, $this->_context[1]);
394
395
                foreach ($pages as $page) {
396
                    ResourceManager::detach(ResourceManager::RESOURCE_TYPE_EVENT, $this->_context[1], $page['id']);
397
                }
398
399
                redirect(SYMPHONY_URL . '/blueprints/events/');
0 ignored issues
show
Bug introduced by
The constant SYMPHONY_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
400
            }
401
        }
402
    }
403
404
    public function __actionIndex($resource_type)
405
    {
406
        return parent::__actionIndex(ResourceManager::RESOURCE_TYPE_EVENT);
0 ignored issues
show
Bug introduced by
Are you sure the usage of parent::__actionIndex(Re...r::RESOURCE_TYPE_EVENT) targeting ResourcesPage::__actionIndex() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
407
    }
408
409
    public function __formAction()
410
    {
411
        $fields = $_POST['fields'];
412
        $this->_errors = array();
413
        $providers = Symphony::ExtensionManager()->getProvidersOf(iProvider::EVENT);
414
        $providerClass = null;
415
416
        if (trim($fields['name']) == '') {
417
            $this->_errors['name'] = __('This is a required field');
418
        } elseif (strpos($fields['name'], '\\') !== false) {
419
            $this->_errors['name'] = __('This field contains invalid characters') . ' (\\)';
420
        } elseif (!preg_match('/^[a-z]/i', $fields['name'])) {
421
            $this->_errors['name'] = __('The name of the event must begin with a letter.');
422
        }
423
424
        if (trim($fields['source']) == '') {
425
            $this->_errors['source'] = __('This is a required field');
426
        }
427
428
        $filters = isset($fields['filters']) ? $fields['filters'] : array();
429
430
        // See if a Provided Datasource is saved
431
        if (!empty($providers)) {
432
            foreach ($providers as $providerClass => $provider) {
433
                if ($fields['source'] == call_user_func(array($providerClass, 'getSource'))) {
434
                    call_user_func_array(array($providerClass, 'validate'), array(&$fields, &$this->_errors));
435
                    break;
436
                }
437
438
                unset($providerClass);
439
            }
440
        }
441
442
        $classname = Lang::createHandle($fields['name'], 255, '_', false, true, array('@^[^a-z\d]+@i' => '', '/[^\w\-\.]/i' => ''));
443
        $rootelement = str_replace('_', '-', $classname);
444
        $extends = 'SectionEvent';
445
446
        // Check to make sure the classname is not empty after handlisation.
447
        if (empty($classname) && !isset($this->_errors['name'])) {
448
            $this->_errors['name'] = __('Please ensure name contains at least one Latin-based character.', array($classname));
449
        }
450
451
        $file = EVENTS . '/event.' . $classname . '.php';
0 ignored issues
show
Bug introduced by
The constant EVENTS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
452
        $isDuplicate = false;
453
        $queueForDeletion = null;
454
455
        if ($this->_context[0] == 'new' && is_file($file)) {
456
            $isDuplicate = true;
457
        } elseif ($this->_context[0] == 'edit') {
458
            $existing_handle = $this->_context[1];
459
460
            if ($classname != $existing_handle && is_file($file)) {
461
                $isDuplicate = true;
462
            } elseif ($classname != $existing_handle) {
463
                $queueForDeletion = EVENTS . '/event.' . $existing_handle . '.php';
464
            }
465
        }
466
467
        // Duplicate
468
        if ($isDuplicate) {
469
            $this->_errors['name'] = __('An Event with the name %s already exists', array('<code>' . $classname . '</code>'));
470
        }
471
472
        if (empty($this->_errors)) {
473
            $source = $fields['source'];
474
            $params = array(
475
                'rootelement' => $rootelement,
476
            );
477
478
            $about = array(
479
                'name' => $fields['name'],
480
                'version' => 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'),
481
                'release date' => DateTimeObj::getGMT('c'),
482
                'author name' => Symphony::Author()->getFullName(),
483
                'author website' => URL,
0 ignored issues
show
Bug introduced by
The constant URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
484
                'author email' => Symphony::Author()->get('email')
485
            );
486
487
            // If there is a provider, get their template
488
            if ($providerClass) {
489
                $eventShell = file_get_contents(call_user_func(array($providerClass, 'getTemplate')));
490
            } else {
491
                $eventShell = file_get_contents($this->getTemplate('blueprints.event'));
0 ignored issues
show
Bug introduced by
It seems like $this->getTemplate('blueprints.event') can also be of type false; however, parameter $filename of file_get_contents() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

491
                $eventShell = file_get_contents(/** @scrutinizer ignore-type */ $this->getTemplate('blueprints.event'));
Loading history...
492
                $about['trigger condition'] = $rootelement;
493
            }
494
495
            $this->__injectAboutInformation($eventShell, $about);
496
497
            // Replace the name
498
            $eventShell = str_replace('<!-- CLASS NAME -->', $classname, $eventShell);
499
500
            // Build the templates
501
            if ($providerClass) {
502
                $eventShell = call_user_func(array($providerClass, 'prepare'), $fields, $params, $eventShell);
503
            } else {
504
                $this->__injectFilters($eventShell, $filters);
505
506
                // Add Documentation
507
                $ajaxEventDoc = new contentAjaxEventDocumentation();
508
                $doc_parts = array();
509
510
                // Add Documentation (Success/Failure)
511
                $ajaxEventDoc->addEntrySuccessDoc($doc_parts, $rootelement, $filters);
512
                $ajaxEventDoc->addEntryFailureDoc($doc_parts, $rootelement, $filters);
513
514
                // Filters
515
                $ajaxEventDoc->addDefaultFiltersDoc($doc_parts, $rootelement, $filters);
516
517
                // Frontend Markup
518
                $ajaxEventDoc->addFrontendMarkupDoc($doc_parts, $rootelement, $fields['source'], $filters);
519
                $ajaxEventDoc->addSendMailFilterDoc($doc_parts, $filters);
520
521
                /**
522
                 * Allows adding documentation for new filters. A reference to the $documentation
523
                 * array is provided, along with selected filters
524
                 * @delegate AppendEventFilterDocumentation
525
                 * @param string $context
526
                 * '/blueprints/events/(edit|new|info)/'
527
                 * @param array $selected
528
                 *  An array of all the selected filters for this Event
529
                 * @param array $documentation
530
                 *  An array of all the documentation XMLElements, passed by reference
531
                 * @param string $rootelment
532
                 *  The name of this event, as a handle.
533
                 */
534
                Symphony::ExtensionManager()->notifyMembers('AppendEventFilterDocumentation', '/blueprints/events/', array(
535
                    'selected' => $filters,
536
                    'documentation' => &$doc_parts,
537
                    'rootelement' => $rootelement
538
                ));
539
540
                $documentation = join(PHP_EOL, array_map(function($part) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
541
                    return rtrim($part->generate(true, 4));
542
                }, $doc_parts));
543
                $documentation = str_replace('\'', '\\\'', $documentation);
544
545
                $eventShell = str_replace('<!-- CLASS EXTENDS -->', $extends, $eventShell);
546
                $eventShell = str_replace('<!-- DOCUMENTATION -->', General::tabsToSpaces($documentation, 4), $eventShell);
547
            }
548
549
            $eventShell = str_replace('<!-- ROOT ELEMENT -->', $rootelement, $eventShell);
550
            $eventShell = str_replace('<!-- CLASS NAME -->', $classname, $eventShell);
551
            $eventShell = str_replace('<!-- SOURCE -->', addslashes($source), $eventShell);
552
553
            // Remove left over placeholders
554
            $eventShell = preg_replace(array('/<!--[\w ]++-->/'), '', $eventShell);
555
556
            if ($this->_context[0] == 'new') {
557
                /**
558
                 * Prior to creating an Event, the file path where it will be written to
559
                 * is provided and well as the contents of that file.
560
                 *
561
                 * @delegate EventsPreCreate
562
                 * @since Symphony 2.2
563
                 * @param string $context
564
                 * '/blueprints/events/'
565
                 * @param string $file
566
                 *  The path to the Event file
567
                 * @param string $contents
568
                 *  The contents for this Event as a string passed by reference
569
                 * @param array $filters
570
                 *  An array of the filters attached to this event
571
                 */
572
                Symphony::ExtensionManager()->notifyMembers('EventPreCreate', '/blueprints/events/', array(
573
                    'file' => $file,
574
                    'contents' => &$eventShell,
575
                    'filters' => $filters
576
                ));
577
            } else {
578
                /**
579
                 * Prior to editing an Event, the file path where it will be written to
580
                 * is provided and well as the contents of that file.
581
                 *
582
                 * @delegate EventPreEdit
583
                 * @since Symphony 2.2
584
                 * @param string $context
585
                 * '/blueprints/events/'
586
                 * @param string $file
587
                 *  The path to the Event file
588
                 * @param string $contents
589
                 *  The contents for this Event as a string passed by reference
590
                 * @param array $filters
591
                 *  An array of the filters attached to this event
592
                 */
593
                Symphony::ExtensionManager()->notifyMembers('EventPreEdit', '/blueprints/events/', array(
594
                    'file' => $file,
595
                    'contents' => &$eventShell,
596
                    'filters' => $filters
597
                ));
598
            }
599
600
            // Write the file
601
            if (!General::writeFile($file, $eventShell, Symphony::Configuration()->get('write_mode', 'file'))) {
0 ignored issues
show
Bug introduced by
It seems like Symphony::Configuration(...t('write_mode', 'file') can also be of type array; however, parameter $perm of General::writeFile() does only seem to accept integer|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

601
            if (!General::writeFile($file, $eventShell, /** @scrutinizer ignore-type */ Symphony::Configuration()->get('write_mode', 'file'))) {
Loading history...
602
                $this->pageAlert(
603
                    __('Failed to write Event to disk.')
604
                    . ' ' . __('Please check permissions on %s.', array('<code>/workspace/events</code>')),
605
                    Alert::ERROR
606
                );
607
608
                // Write successful
609
            } else {
610
                if (function_exists('opcache_invalidate')) {
611
                    @opcache_invalidate($file, true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for opcache_invalidate(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

611
                    /** @scrutinizer ignore-unhandled */ @opcache_invalidate($file, true);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
612
                }
613
614
                // Attach this event to pages
615
                $connections = $fields['connections'];
616
                ResourceManager::setPages(ResourceManager::RESOURCE_TYPE_EVENT, is_null($existing_handle) ? $classname : $existing_handle, $connections);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $existing_handle does not seem to be defined for all execution paths leading up to this point.
Loading history...
617
618
                if ($queueForDeletion) {
619
                    General::deleteFile($queueForDeletion);
620
621
                    $pages = PageManager::fetch(false, array('events', 'id'), array("
622
                        `events` REGEXP '[[:<:]]" . $existing_handle . "[[:>:]]'
623
                    "));
624
625
                    if (is_array($pages) && !empty($pages)) {
626
                        foreach ($pages as $page) {
627
                            $page['events'] = preg_replace('/\b'.$existing_handle.'\b/i', $classname, $page['events']);
628
629
                            PageManager::edit($page['id'], $page);
630
                        }
631
                    }
632
                }
633
634
                if ($this->_context[0] == 'new') {
635
                    /**
636
                     * After creating the Event, the path to the Event file is provided
637
                     *
638
                     * @delegate EventPostCreate
639
                     * @since Symphony 2.2
640
                     * @param string $context
641
                     * '/blueprints/events/'
642
                     * @param string $file
643
                     *  The path to the Event file
644
                     */
645
                    Symphony::ExtensionManager()->notifyMembers('EventPostCreate', '/blueprints/events/', array(
646
                        'file' => $file
647
                    ));
648
                } else {
649
                    /**
650
                     * After editing the Event, the path to the Event file is provided
651
                     *
652
                     * @delegate EventPostEdit
653
                     * @since Symphony 2.2
654
                     * @param string $context
655
                     * '/blueprints/events/'
656
                     * @param string $file
657
                     *  The path to the Event file
658
                     * @param string $previous_file
659
                     *  The path of the previous Event file in the case where an Event may
660
                     *  have been renamed. To get the handle from this value, see
661
                     *  `EventManager::__getHandleFromFilename`
662
                     */
663
                    Symphony::ExtensionManager()->notifyMembers('EventPostEdit', '/blueprints/events/', array(
664
                        'file' => $file,
665
                        'previous_file' => ($queueForDeletion) ? $queueForDeletion : null
666
                    ));
667
                }
668
669
                redirect(SYMPHONY_URL . '/blueprints/events/edit/'.$classname.'/'.($this->_context[0] == 'new' ? 'created' : 'saved') . '/');
0 ignored issues
show
Coding Style introduced by
Inline shorthand IF statement requires brackets around comparison
Loading history...
Bug introduced by
The constant SYMPHONY_URL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
670
            }
671
        }
672
    }
673
674
    public function __injectFilters(&$shell, $elements)
675
    {
676
        if (!is_array($elements) || empty($elements)) {
677
            return;
678
        }
0 ignored issues
show
Coding Style introduced by
No blank line found after control structure
Loading history...
679
        $elements = array_map('addslashes', $elements);
680
        $shell = str_replace('<!-- FILTERS -->', "'" . implode("'," . PHP_EOL . "        '", $elements) . "'", $shell);
681
    }
682
683
    public function __injectAboutInformation(&$shell, $details)
684
    {
685
        if (!is_array($details) || empty($details)) {
686
            return;
687
        }
688
689
        foreach ($details as $key => $val) {
690
            if (!is_string($key) || !is_string($val)) {
691
                continue;
692
            }
693
694
            $shell = str_replace('<!-- ' . strtoupper(addslashes($key)) . ' -->', addslashes($val), $shell);
695
        }
696
    }
697
}
698