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.
Completed
Push — integration ( 45cc9f...98bc42 )
by Brendan
05:52
created

contentBlueprintsEvents::__form()   F

Complexity

Conditions 52
Paths > 20000

Size

Total Lines 309
Code Lines 191

Duplication

Lines 63
Ratio 20.39 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 52
eloc 191
c 2
b 0
f 0
nc 429496.7295
nop 1
dl 63
loc 309
rs 2

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
12
{
13
    public $_errors = array();
14
15 View Code Duplication
    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
__form uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
39
    {
40
        $formHasErrors = (is_array($this->_errors) && !empty($this->_errors));
41
42 View Code Duplication
        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['flag'])) {
50
            $time = Widget::Time();
51
52
            switch ($this->_context['flag']) {
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
Bug introduced by
The variable $message 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...
62
                . ' <a href="' . SYMPHONY_URL . '/blueprints/events/new/" accesskey="c">'
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);
72
        $fields = array("name"=>null, "filters"=>null);
73
        $about = array("name"=>null);
74
        $providers = Symphony::ExtensionManager()->getProvidersOf(iProvider::EVENT);
75
76
        if (isset($_POST['fields'])) {
77
            $fields = $_POST['fields'];
78
79
            if ($this->_context['action'] === 'edit') {
80
                $isEditing = true;
81
            }
82
        } elseif ($this->_context['action'] === 'edit' || $this->_context['action'] === 'info') {
83
            $isEditing = true;
84
            $handle = $this->_context['handle'];
85
            $existing = EventManager::create($handle);
86
            $about = $existing->about();
0 ignored issues
show
Bug introduced by
The method about() does not seem to exist on object<Event>.

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...
87
88
            if ($this->_context['action'] === 'edit' && !$existing->allowEditorToParse()) {
89
                redirect(SYMPHONY_URL . '/blueprints/events/info/' . $handle . '/');
90
            }
91
92
            $fields['name'] = $about['name'];
93
            $fields['source'] = $existing->getSource();
94
            $provided = false;
95
96 View Code Duplication
            if (!empty($providers)) {
97
                foreach ($providers as $providerClass => $provider) {
98
                    if ($fields['source'] === call_user_func(array($providerClass, 'getClass'))) {
99
                        $fields = array_merge($fields, $existing->settings());
0 ignored issues
show
Bug introduced by
The method settings() does not seem to exist on object<Event>.

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...
100
                        $provided = true;
101
                        break;
102
                    }
103
                }
104
            }
105
106
            if (!$provided) {
107
                if (isset($existing->eParamFILTERS)) {
108
                    $fields['filters'] = $existing->eParamFILTERS;
0 ignored issues
show
Bug introduced by
The property eParamFILTERS does not seem to exist in Event.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
109
                }
110
            }
111
        }
112
113
        // Handle name on edited changes, or from reading an edited datasource
114 View Code Duplication
        if (isset($about['name'])) {
115
            $name = $about['name'];
116
        } elseif (isset($fields['name'])) {
117
            $name = $fields['name'];
118
        }
119
120
        $this->setPageType('form');
121
        $this->setTitle(__(($isEditing ? '%1$s &ndash; %2$s &ndash; %3$s' : '%2$s &ndash; %3$s'), array($name, __('Events'), __('Symphony'))));
0 ignored issues
show
Bug introduced by
The variable $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...
122
        $this->appendSubheading(($isEditing ? $about['name'] : __('Untitled')));
123
        $this->insertBreadcrumbs(array(
124
            Widget::Anchor(__('Events'), SYMPHONY_URL . '/blueprints/events/'),
125
        ));
126
127
        if (!$readonly) {
128
            $fieldset = new XMLElement('fieldset');
129
            $fieldset->setAttribute('class', 'settings');
130
            $fieldset->appendChild(new XMLElement('legend', __('Essentials')));
131
132
            // Target
133
            $sources = new XMLElement('div', null, array('class' => 'apply actions'));
134
            $div = new XMLElement('div');
135
            $label = Widget::Label(__('Target'), null, 'apply-label-left');
136
            $sources->appendChild($label);
137
            $sources->appendChild($div);
138
139
            $sections = SectionManager::fetch(null, 'ASC', 'name');
140
            $options = array();
141
            $section_options = array();
142
            $source = isset($fields['source']) ? $fields['source'] : null;
143
144
            if (is_array($sections) && !empty($sections)) {
145
                $section_options = array('label' => __('Sections'), 'options' => array());
146
147 View Code Duplication
                foreach ($sections as $s) {
148
                    $section_options['options'][] = array($s->get('id'), $source === $s->get('id'), General::sanitize($s->get('name')));
149
                }
150
            }
151
152
            $options[] = $section_options;
153
154
            // Loop over the event providers
155
            if (!empty($providers)) {
156
                $p = array('label' => __('From extensions'), 'options' => array());
157
158
                foreach ($providers as $providerClass => $provider) {
159
                    $p['options'][] = array(
160
                        $providerClass, ($fields['source'] === $providerClass), $provider
161
                    );
162
                }
163
164
                $options[] = $p;
165
            }
166
167
            $div->appendChild(
168
                Widget::Select('source', $options, array('id' => 'event-context'))
169
            );
170
171
            if (isset($this->_errors['source'])) {
172
                $this->Context->prependChild(Widget::Error($sources, $this->_errors['source']));
173
            } else {
174
                $this->Context->prependChild($sources);
175
            }
176
177
            $this->Form->appendChild(
178
                Widget::Input('fields[source]', $options[0]['options'][0][0], 'hidden', array('id' => 'event-source'))
179
            );
180
181
            // Name
182
            $group = new XMLElement('div');
183
            $label = Widget::Label(__('Name'));
184
            $label->appendChild(Widget::Input('fields[name]', General::sanitize($fields['name'])));
185
186
            $div = new XMLElement('div');
187
            $div->setAttribute('class', 'column');
188
189 View Code Duplication
            if (isset($this->_errors['name'])) {
190
                $div->appendChild(Widget::Error($label, $this->_errors['name']));
191
            } else {
192
                $div->appendChild($label);
193
            }
194
            $group->appendChild($div);
195
            $fieldset->appendChild($group);
196
            $this->Form->appendChild($fieldset);
197
198
            // Filters
199
            $fieldset = new XMLElement('fieldset');
200
            $fieldset->setAttribute('class', 'settings pickable');
201
            $fieldset->appendChild(new XMLElement('legend', __('Filters')));
202
            $p = new XMLElement('p', __('Event Filters add additional conditions or actions to an event.'));
203
            $p->setAttribute('class', 'help');
204
            $fieldset->appendChild($p);
205
206
            $filters = isset($fields['filters']) ? $fields['filters'] : array();
207
            $options = array(
208
                array('admin-only', in_array('admin-only', $filters), __('Admin Only')),
209
                array('send-email', in_array('send-email', $filters), __('Send Notification Email')),
210
                array('expect-multiple', in_array('expect-multiple', $filters), __('Allow Multiple')),
211
            );
212
213
            /**
214
             * Allows adding of new filter rules to the Event filter rule select box
215
             *
216
             * @delegate AppendEventFilter
217
             * @param string $context
218
             * '/blueprints/events/(edit|new|info)/'
219
             * @param array $selected
220
             *  An array of all the selected filters for this Event
221
             * @param array $options
222
             *  An array of all the filters that are available, passed by reference
223
             */
224
            Symphony::ExtensionManager()->notifyMembers('AppendEventFilter', '/blueprints/events/' . $this->_context['action'] . '/', array(
225
                'selected' => $filters,
226
                'options' => &$options
227
            ));
228
229
            $fieldset->appendChild(Widget::Select('fields[filters][]', $options, array('multiple' => 'multiple', 'id' => 'event-filters')));
230
            $this->Form->appendChild($fieldset);
231
232
            // Connections
233
            $fieldset = new XMLElement('fieldset');
234
            $fieldset->setAttribute('class', 'settings');
235
            $fieldset->appendChild(new XMLElement('legend', __('Attach to Pages')));
236
            $p = new XMLElement('p', __('The event will only be available on the selected pages.'));
237
            $p->setAttribute('class', 'help');
238
            $fieldset->appendChild($p);
239
240
            $div = new XMLElement('div');
241
            $label = Widget::Label(__('Pages'));
242
243
            $pages = PageManager::fetch();
244
            $event_handle = str_replace('-', '_', Lang::createHandle($fields['name']));
245
            $connections = ResourceManager::getAttachedPages(ResourceManager::RESOURCE_TYPE_EVENT, $event_handle);
246
            $selected = array();
247
248
            foreach ($connections as $connection) {
249
                $selected[] = $connection['id'];
250
            }
251
252
            $options = array();
253
254 View Code Duplication
            foreach ($pages as $page) {
0 ignored issues
show
Bug introduced by
The expression $pages of type array|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
255
                $options[] = array($page['id'], in_array($page['id'], $selected), PageManager::resolvePageTitle($page['id']));
256
            }
257
258
            $label->appendChild(Widget::Select('fields[connections][]', $options, array('multiple' => 'multiple')));
259
            $div->appendChild($label);
260
261
            $fieldset->appendChild($div);
262
            $this->Form->appendChild($fieldset);
263
264
            // Providers
265
            if (!empty($providers)) {
266
                foreach ($providers as $providerClass => $provider) {
267
                    if ($isEditing && $fields['source'] !== call_user_func(array($providerClass, 'getSource'))) {
268
                        continue;
269
                    }
270
271
                    call_user_func_array(array($providerClass, 'buildEditor'), array($this->Form, &$this->_errors, $fields, $handle));
0 ignored issues
show
Bug introduced by
The variable $handle 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...
272
                }
273
            }
274
        } else {
275
            // Author
276
            if (isset($about['author']['website'])) {
277
                $link = Widget::Anchor($about['author']['name'], General::validateURL($about['author']['website']));
278
            } elseif (isset($about['author']['email'])) {
279
                $link = Widget::Anchor($about['author']['name'], 'mailto:' . $about['author']['email']);
280
            } else {
281
                $link = $about['author']['name'];
282
            }
283
284
            if ($link) {
285
                $fieldset = new XMLElement('fieldset');
286
                $fieldset->setAttribute('class', 'settings');
287
                $fieldset->appendChild(new XMLElement('legend', __('Author')));
288
                $fieldset->appendChild(new XMLElement('p', $link->generate(false)));
289
                $this->Form->appendChild($fieldset);
290
            }
291
292
            // Version
293
            $fieldset = new XMLElement('fieldset');
294
            $fieldset->setAttribute('class', 'settings');
295
            $fieldset->appendChild(new XMLElement('legend', __('Version')));
296
            $version = array_key_exists('version', $about) ? $about['version'] : null;
297
            $release_date = array_key_exists('release-date', $about) ? $about['release-date'] : filemtime(EventManager::__getDriverPath($handle));
298
299
            if (preg_match('/^\d+(\.\d+)*$/', $version)) {
300
                $fieldset->appendChild(
301
                    new XMLElement('p', __('%1$s released on %2$s', array($version, DateTimeObj::format($release_date, __SYM_DATE_FORMAT__))))
302
                );
303 View Code Duplication
            } elseif (!is_null($version)) {
304
                $fieldset->appendChild(
305
                    new XMLElement('p', __('Created by %1$s at %2$s', array($version, DateTimeObj::format($release_date, __SYM_DATE_FORMAT__))))
306
                );
307
            } else {
308
                $fieldset->appendChild(
309
                    new XMLElement('p', __('Last modified on %s', array(DateTimeObj::format($release_date, __SYM_DATE_FORMAT__))))
310
                );
311
            }
312
            $this->Form->appendChild($fieldset);
313
        }
314
315
        // If we are editing an event, it assumed that the event has documentation
316
        $fieldset = new XMLElement('fieldset');
317
        $fieldset->setAttribute('id', 'event-documentation');
318
        $fieldset->setAttribute('class', 'settings');
319
320
        if ($isEditing && method_exists($existing, 'documentation')) {
321
            $doc = $existing->documentation();
0 ignored issues
show
Bug introduced by
The variable $existing 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...
322
323
            if ($doc) {
324
                $fieldset->setValue(
325
                    '<legend>' . __('Documentation') . '</legend>' . PHP_EOL .
326
                    General::tabsToSpaces(is_object($doc) ? $doc->generate(true, 4) : $doc)
327
                );
328
            }
329
        }
330
331
        $this->Form->appendChild($fieldset);
332
333
        $div = new XMLElement('div');
334
        $div->setAttribute('class', 'actions');
335
        $div->appendChild(Widget::Input('action[save]', ($isEditing ? __('Save Changes') : __('Create Event')), 'submit', array('accesskey' => 's')));
336
337 View Code Duplication
        if ($isEditing) {
338
            $button = new XMLElement('button', __('Delete'));
339
            $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?')));
340
            $div->appendChild($button);
341
        }
342
343
        if (!$readonly) {
344
            $this->Form->appendChild($div);
345
        }
346
    }
347
348
    public function __actionNew()
0 ignored issues
show
Coding Style introduced by
__actionNew uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
349
    {
350
        if (array_key_exists('save', $_POST['action'])) {
351
            return $this->__formAction();
352
        }
353
    }
354
355 View Code Duplication
    public function __actionEdit()
0 ignored issues
show
Coding Style introduced by
__actionEdit uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
356
    {
357
        if (array_key_exists('save', $_POST['action'])) {
358
            return $this->__formAction();
359
        } elseif (array_key_exists('delete', $_POST['action'])) {
360
            /**
361
             * Prior to deleting the Event file. Target file path is provided.
362
             *
363
             * @delegate EventPreDelete
364
             * @since Symphony 2.2
365
             * @param string $context
366
             * '/blueprints/events/'
367
             * @param string $file
368
             *  The path to the Event file
369
             */
370
            Symphony::ExtensionManager()->notifyMembers('EventPreDelete', '/blueprints/events/', array('file' => EVENTS . "/event." . $this->_context['handle'] . ".php"));
371
372
            if (!General::deleteFile(EVENTS . '/event.' . $this->_context['handle'] . '.php')) {
373
                $this->pageAlert(
374
                    __('Failed to delete %s.', array('<code>' . $this->_context['handle'] . '</code>'))
375
                    . ' ' . __('Please check permissions on %s.', array('<code>/workspace/events</code>')),
376
                    Alert::ERROR
377
                );
378
            } else {
379
                $pages = ResourceManager::getAttachedPages(ResourceManager::RESOURCE_TYPE_EVENT, $this->_context['handle']);
380
381
                foreach ($pages as $page) {
382
                    ResourceManager::detach(ResourceManager::RESOURCE_TYPE_EVENT, $this->_context['handle'], $page['id']);
383
                }
384
385
                redirect(SYMPHONY_URL . '/blueprints/events/');
386
            }
387
        }
388
    }
389
390
    public function __actionIndex($resource_type)
391
    {
392
        return parent::__actionIndex(ResourceManager::RESOURCE_TYPE_EVENT);
393
    }
394
395
    public function __formAction()
0 ignored issues
show
Coding Style introduced by
__formAction uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
396
    {
397
        $fields = $_POST['fields'];
398
        $this->_errors = array();
399
        $providers = Symphony::ExtensionManager()->getProvidersOf(iProvider::EVENT);
400
        $providerClass = null;
401
402 View Code Duplication
        if (trim($fields['name']) === '') {
403
            $this->_errors['name'] = __('This is a required field');
404
        }
405
406 View Code Duplication
        if (trim($fields['source']) === '') {
407
            $this->_errors['source'] = __('This is a required field');
408
        }
409
410
        $filters = isset($fields['filters']) ? $fields['filters'] : array();
411
412
        // See if a Provided Datasource is saved
413 View Code Duplication
        if (!empty($providers)) {
414
            foreach ($providers as $providerClass => $provider) {
415
                if ($fields['source'] === call_user_func(array($providerClass, 'getSource'))) {
416
                    call_user_func_array(array($providerClass, 'validate'), array(&$fields, &$this->_errors));
417
                    break;
418
                }
419
420
                unset($providerClass);
421
            }
422
        }
423
424
        $classname = Lang::createHandle($fields['name'], 255, '_', false, true, array('@^[^a-z\d]+@i' => '', '/[^\w-\.]/i' => ''));
425
        $rootelement = str_replace('_', '-', $classname);
426
        $extends = 'SectionEvent';
427
428
        // Check to make sure the classname is not empty after handlisation.
429 View Code Duplication
        if (empty($classname) && !isset($this->_errors['name'])) {
430
            $this->_errors['name'] = __('Please ensure name contains at least one Latin-based character.', array($classname));
431
        }
432
433
        $file = EVENTS . '/event.' . $classname . '.php';
434
        $isDuplicate = false;
435
        $queueForDeletion = null;
436
437 View Code Duplication
        if ($this->_context['action'] === 'new' && is_file($file)) {
438
            $isDuplicate = true;
439
        } elseif ($this->_context['action'] === 'edit') {
440
            $existing_handle = $this->_context['handle'];
441
442
            if ($classname !== $existing_handle && is_file($file)) {
443
                $isDuplicate = true;
444
            } elseif ($classname !== $existing_handle) {
445
                $queueForDeletion = EVENTS . '/event.' . $existing_handle . '.php';
446
            }
447
        }
448
449
        // Duplicate
450 View Code Duplication
        if ($isDuplicate) {
451
            $this->_errors['name'] = __('An Event with the name %s already exists', array('<code>' . $classname . '</code>'));
452
        }
453
454
        if (empty($this->_errors)) {
455
            $source = $fields['source'];
456
            $params = array(
457
                'rootelement' => $rootelement,
458
            );
459
460
            $about = array(
461
                'name' => $fields['name'],
462
                'version' => 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'),
463
                'release date' => DateTimeObj::getGMT('c'),
464
                'author name' => Symphony::Author()->getFullName(),
465
                'author website' => URL,
466
                'author email' => Symphony::Author()->get('email')
467
            );
468
469
            // If there is a provider, get their template
470
            if ($providerClass) {
471
                $eventShell = file_get_contents(call_user_func(array($providerClass, 'getTemplate')));
472
            } else {
473
                $eventShell = file_get_contents($this->getTemplate('blueprints.event'));
474
                $about['trigger condition'] = $rootelement;
475
            }
476
477
            $this->__injectAboutInformation($eventShell, $about);
478
479
            // Replace the name
480
            $eventShell = str_replace('<!-- CLASS NAME -->', $classname, $eventShell);
481
482
            // Build the templates
483
            if ($providerClass) {
484
                $eventShell = call_user_func(array($providerClass, 'prepare'), $fields, $params, $eventShell);
485
            } else {
486
                $this->__injectFilters($eventShell, $filters);
487
488
                // Add Documentation
489
                $ajaxEventDoc = new contentAjaxEventDocumentation();
490
                $doc_parts = array();
491
492
                // Add Documentation (Success/Failure)
493
                $ajaxEventDoc->addEntrySuccessDoc($doc_parts, $rootelement, $filters);
494
                $ajaxEventDoc->addEntryFailureDoc($doc_parts, $rootelement, $filters);
495
496
                // Filters
497
                $ajaxEventDoc->addDefaultFiltersDoc($doc_parts, $rootelement, $filters);
498
499
                // Frontend Markup
500
                $ajaxEventDoc->addFrontendMarkupDoc($doc_parts, $rootelement, $fields['source'], $filters);
501
                $ajaxEventDoc->addSendMailFilterDoc($doc_parts, $filters);
502
503
                /**
504
                 * Allows adding documentation for new filters. A reference to the $documentation
505
                 * array is provided, along with selected filters
506
                 * @delegate AppendEventFilterDocumentation
507
                 * @param string $context
508
                 * '/blueprints/events/(edit|new|info)/'
509
                 * @param array $selected
510
                 *  An array of all the selected filters for this Event
511
                 * @param array $documentation
512
                 *  An array of all the documentation XMLElements, passed by reference
513
                 * @param string $rootelment
514
                 *  The name of this event, as a handle.
515
                 */
516
                Symphony::ExtensionManager()->notifyMembers('AppendEventFilterDocumentation', '/blueprints/events/', array(
517
                    'selected' => $filters,
518
                    'documentation' => &$doc_parts,
519
                    'rootelement' => $rootelement
520
                ));
521
522
                $documentation = join(PHP_EOL, array_map(function($part) {
523
                    return rtrim($part->generate(true, 4));
524
                }, $doc_parts));
525
                $documentation = str_replace('\'', '\\\'', $documentation);
526
527
                $eventShell = str_replace('<!-- CLASS EXTENDS -->', $extends, $eventShell);
528
                $eventShell = str_replace('<!-- DOCUMENTATION -->', General::tabsToSpaces($documentation, 4), $eventShell);
529
            }
530
531
            $eventShell = str_replace('<!-- ROOT ELEMENT -->', $rootelement, $eventShell);
532
            $eventShell = str_replace('<!-- CLASS NAME -->', $classname, $eventShell);
533
            $eventShell = str_replace('<!-- SOURCE -->', $source, $eventShell);
534
535
            // Remove left over placeholders
536
            $eventShell = preg_replace(array('/<!--[\w ]++-->/'), '', $eventShell);
537
538
            if ($this->_context['action'] === 'new') {
539
                /**
540
                 * Prior to creating an Event, the file path where it will be written to
541
                 * is provided and well as the contents of that file.
542
                 *
543
                 * @delegate EventsPreCreate
544
                 * @since Symphony 2.2
545
                 * @param string $context
546
                 * '/blueprints/events/'
547
                 * @param string $file
548
                 *  The path to the Event file
549
                 * @param string $contents
550
                 *  The contents for this Event as a string passed by reference
551
                 * @param array $filters
552
                 *  An array of the filters attached to this event
553
                 */
554
                Symphony::ExtensionManager()->notifyMembers('EventPreCreate', '/blueprints/events/', array(
555
                    'file' => $file,
556
                    'contents' => &$eventShell,
557
                    'filters' => $filters
558
                ));
559
            } else {
560
                /**
561
                 * Prior to editing an Event, the file path where it will be written to
562
                 * is provided and well as the contents of that file.
563
                 *
564
                 * @delegate EventPreEdit
565
                 * @since Symphony 2.2
566
                 * @param string $context
567
                 * '/blueprints/events/'
568
                 * @param string $file
569
                 *  The path to the Event file
570
                 * @param string $contents
571
                 *  The contents for this Event as a string passed by reference
572
                 * @param array $filters
573
                 *  An array of the filters attached to this event
574
                 */
575
                Symphony::ExtensionManager()->notifyMembers('EventPreEdit', '/blueprints/events/', array(
576
                    'file' => $file,
577
                    'contents' => &$eventShell,
578
                    'filters' => $filters
579
                ));
580
            }
581
582
            // Write the file
583 View Code Duplication
            if (!is_writable(dirname($file)) || !General::writeFile($file, $eventShell, Symphony::Configuration()->get('write_mode', 'file'))) {
0 ignored issues
show
Documentation introduced by
\Symphony::Configuration...t('write_mode', 'file') is of type array|string, but the function expects a integer.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
584
                $this->pageAlert(
585
                    __('Failed to write Event to disk.')
586
                    . ' ' . __('Please check permissions on %s.', array('<code>/workspace/events</code>')),
587
                    Alert::ERROR
588
                );
589
590
                // Write successful
591
            } else {
592
                if (function_exists('opcache_invalidate')) {
593
                    opcache_invalidate($file, true);
594
                }
595
596
                // Attach this event to pages
597
                $connections = $fields['connections'];
598
                ResourceManager::setPages(ResourceManager::RESOURCE_TYPE_EVENT, is_null($existing_handle) ? $classname : $existing_handle, $connections);
0 ignored issues
show
Bug introduced by
The variable $existing_handle 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...
599
600
                if ($queueForDeletion) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $queueForDeletion of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
601
                    General::deleteFile($queueForDeletion);
602
603
                    $pages = PageManager::fetch(false, array('events', 'id'), array("
604
                        `events` REGEXP '[[:<:]]" . $existing_handle . "[[:>:]]'
605
                    "));
606
607
                    if (is_array($pages) && !empty($pages)) {
608
                        foreach ($pages as $page) {
609
                            $page['events'] = preg_replace('/\b'.$existing_handle.'\b/i', $classname, $page['events']);
610
611
                            PageManager::edit($page['id'], $page);
612
                        }
613
                    }
614
                }
615
616
                if ($this->_context['action'] === 'new') {
617
                    /**
618
                     * After creating the Event, the path to the Event file is provided
619
                     *
620
                     * @delegate EventPostCreate
621
                     * @since Symphony 2.2
622
                     * @param string $context
623
                     * '/blueprints/events/'
624
                     * @param string $file
625
                     *  The path to the Event file
626
                     */
627
                    Symphony::ExtensionManager()->notifyMembers('EventPostCreate', '/blueprints/events/', array(
628
                        'file' => $file
629
                    ));
630
                } else {
631
                    /**
632
                     * After editing the Event, the path to the Event file is provided
633
                     *
634
                     * @delegate EventPostEdit
635
                     * @since Symphony 2.2
636
                     * @param string $context
637
                     * '/blueprints/events/'
638
                     * @param string $file
639
                     *  The path to the Event file
640
                     * @param string $previous_file
641
                     *  The path of the previous Event file in the case where an Event may
642
                     *  have been renamed. To get the handle from this value, see
643
                     *  `EventManager::__getHandleFromFilename`
644
                     */
645
                    Symphony::ExtensionManager()->notifyMembers('EventPostEdit', '/blueprints/events/', array(
646
                        'file' => $file,
647
                        'previous_file' => ($queueForDeletion) ? $queueForDeletion : null
648
                    ));
649
                }
650
651
                redirect(SYMPHONY_URL . '/blueprints/events/edit/'. $classname . '/' . ($this->_context['action'] === 'new' ? 'created' : 'saved') . '/');
652
            }
653
        }
654
    }
655
656
    public function __injectFilters(&$shell, $elements)
657
    {
658
        if (!is_array($elements) || empty($elements)) {
659
            return;
660
        }
661
662
        $shell = str_replace('<!-- FILTERS -->', "'" . implode("'," . PHP_EOL . "\t\t\t\t'", $elements) . "'", $shell);
663
    }
664
665 View Code Duplication
    public function __injectAboutInformation(&$shell, $details)
666
    {
667
        if (!is_array($details) || empty($details)) {
668
            return;
669
        }
670
671
        foreach ($details as $key => $val) {
672
            $shell = str_replace('<!-- ' . strtoupper($key) . ' -->', addslashes($val), $shell);
673
        }
674
    }
675
}
676