Completed
Push — develop ( 55adb8...cd5d3f )
by John
03:07
created

ArticleView::editView()   B

Complexity

Conditions 7
Paths 64

Size

Total Lines 59
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 59
rs 7.5346
c 1
b 0
f 0
cc 7
eloc 28
nc 64
nop 1

How to fix   Long Method   

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
namespace Alpha\View;
4
5
use Alpha\Util\Config\ConfigProvider;
6
use Alpha\Util\Extension\MarkdownFacade;
7
use Alpha\Util\Security\SecurityUtils;
8
use Alpha\View\Widget\Button;
9
use Alpha\Controller\Front\FrontController;
10
11
/**
12
 * The rendering class for the Article class.
13
 *
14
 * @since 1.0
15
 *
16
 * @author John Collins <[email protected]>
17
 * @license http://www.opensource.org/licenses/bsd-license.php The BSD License
18
 * @copyright Copyright (c) 2017, John Collins (founder of Alpha Framework).
19
 * All rights reserved.
20
 *
21
 * <pre>
22
 * Redistribution and use in source and binary forms, with or
23
 * without modification, are permitted provided that the
24
 * following conditions are met:
25
 *
26
 * * Redistributions of source code must retain the above
27
 *   copyright notice, this list of conditions and the
28
 *   following disclaimer.
29
 * * Redistributions in binary form must reproduce the above
30
 *   copyright notice, this list of conditions and the
31
 *   following disclaimer in the documentation and/or other
32
 *   materials provided with the distribution.
33
 * * Neither the name of the Alpha Framework nor the names
34
 *   of its contributors may be used to endorse or promote
35
 *   products derived from this software without specific
36
 *   prior written permission.
37
 *
38
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
39
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
40
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
41
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
43
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
48
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
49
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
51
 * </pre>
52
 */
53
class ArticleView extends View
54
{
55
    /**
56
     * Method to generate the markdown HTML render of the article content.
57
     *
58
     * @param array $fields Hash array of HTML fields to pass to the template.
59
     *
60
     * @since 1.0
61
     *
62
     * @return string
63
     */
64
    public function markdownView($fields = array())
65
    {
66
        $markdown = new MarkdownFacade($this->record);
67
68
        $fields['markdownContent'] = $markdown->getContent();
69
70
        return $this->loadTemplate($this->record, 'markdown', $fields);
71
    }
72
73
    /**
74
     * Adds a note to the create article screen.
75
     *
76
     * @return string
77
     *
78
     * @since 1.0
79
     */
80
    protected function after_createView_callback()
81
    {
82
        return '<p><strong>Please note</strong> that you will only be able to attach files to the article once it has been created.</p><br>';
83
    }
84
85
    /**
86
     * Renders the list view (adds the dateAdded field for the list template).
87
     *
88
     * @param array $fields hash array of HTML fields to pass to the template
89
     *
90
     * @since 1.0
91
     *
92
     * @return string
93
     */
94
    public function listView($fields = array())
95
    {
96
        $fields['dateAdded'] = $this->record->getCreateTS()->getDate();
97
        $fields['editButtonURL'] = FrontController::generateSecureURL('act=Alpha\Controller\ArticleController&ActiveRecordType='.get_class($this->record).'&ActiveRecordID='.$this->record->getID().'&view=edit');
98
99
        return parent::listView($fields);
100
    }
101
102
    /**
103
     * Renders the admin view for the Article, with create button pointed to the ArticleController.
104
     *
105
     * @param array $fields Hash array of fields to pass to the template
106
     *
107
     * @return string
108
     *
109
     * @since 2.0.1
110
     */
111
    public function adminView($fields = array())
112
    {
113
        $fields['createButtonURL'] = FrontController::generateSecureURL('act=Alpha\Controller\ArticleController&ActiveRecordType='.get_class($this->record).'&view=create');
114
115
        return parent::adminView($fields);
116
    }
117
118
    /**
119
     * Renders the detail view for the Article, with edit button pointed to the ArticleController.
120
     *
121
     * @param array $fields Hash array of fields to pass to the template
122
     *
123
     * @return string
124
     *
125
     * @since 2.0.1
126
     */
127
    public function detailedView($fields = array())
128
    {
129
        $fields['editButtonURL'] = FrontController::generateSecureURL('act=Alpha\Controller\ArticleController&ActiveRecordType='.get_class($this->record).'&ActiveRecordID='.$this->record->getID().'&view=edit');
130
131
        return parent::detailedView($fields);
132
    }
133
134
    /**
135
     * Renders a form to enable article editing with attachments options.
136
     *
137
     * @param array $fields hash array of HTML fields to pass to the template
138
     *
139
     * @since 1.0
140
     *
141
     * @return string
142
     */
143
    public function editView($fields = array())
144
    {
145
        if (method_exists($this, 'before_editView_callback')) {
146
            $this->{'before_editView_callback'}();
147
        }
148
149
        $config = ConfigProvider::getInstance();
150
151
        // the form action
152
        if (isset($fields['URI'])) {
153
            $fields['formAction'] = $fields['URI'];
154
        }
155
156
        // the form ID
157
        $fields['formID'] = stripslashes(get_class($this->record)).'_'.$this->record->getID();
158
159
        // buffer form fields to $formFields
160
        $fields['formFields'] = $this->renderAllFields('edit');
161
162
        // buffer HTML output for Create and Cancel buttons
163
        $button = new Button('submit', 'Save', 'saveBut');
164
        $fields['saveButton'] = $button->render();
165
166
        $formFieldId = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('ActiveRecordID')) : 'ActiveRecordID');
167
            
168
        $js = View::loadTemplateFragment('html', 'bootstrapconfirmokay.phtml', array('prompt' => 'Are you sure you wish to delete this item?', 'formFieldId' => $formFieldId, 'formFieldValue' => $this->record->getID(), 'formId' => 'deleteForm'));
169
170
        $button = new Button($js, 'Delete', 'deleteBut');
171
        $fields['deleteButton'] = $button->render();
172
173
        $button = new Button("document.location = '".FrontController::generateSecureURL('act=Alpha\Controller\ActiveRecordController&ActiveRecordType='.get_class($this->record).'&start=0&limit='.$config->get('app.list.page.amount'))."'", 'Back to List', 'cancelBut');
174
        $fields['cancelButton'] = $button->render();
175
176
        $tags = array();
177
178
        if (is_object($this->record->getPropObject('tags'))) {
179
            $tags = $this->record->getPropObject('tags')->getRelated();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Alpha\Model\Type\Type as the method getRelated() does only exist in the following sub-classes of Alpha\Model\Type\Type: Alpha\Model\Type\Relation. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
180
        }
181
182
        if (count($tags) > 0) {
183
            $button = new Button("document.location = '".FrontController::generateSecureURL('act=Alpha\Controller\TagController&ActiveRecordType='.get_class($this->record).'&ActiveRecordID='.$this->record->getID())."'", 'Edit Tags', 'tagsBut');
184
            $fields['tagsButton'] = $button->render();
185
        }
186
187
        // buffer security fields to $formSecurityFields variable
188
        $fields['formSecurityFields'] = $this->renderSecurityFields();
189
190
        // ID will need to be posted for optimistic lock checking
191
        $fields['version_num'] = $this->record->getVersionNumber();
192
193
        // file attachments section
194
        $fields['fileAttachments'] = $this->renderFileUploadSection();
195
196
        if (method_exists($this, 'after_editView_callback')) {
197
            $this->{'after_editView_callback'}();
198
        }
199
200
        return $this->loadTemplate($this->record, 'edit', $fields);
201
    }
202
203
    /**
204
     * Renders the HTML for the file upload section.
205
     *
206
     * @return string
207
     *
208
     * @since 1.0
209
     */
210
    protected function renderFileUploadSection()
211
    {
212
        $config = ConfigProvider::getInstance();
213
214
        $html = '<div class="form-group">';
215
        $html .= '  <h3>File Attachments:</h3>';
216
217
        if (is_dir($this->record->getAttachmentsLocation())) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Alpha\Model\ActiveRecord as the method getAttachmentsLocation() does only exist in the following sub-classes of Alpha\Model\ActiveRecord: Alpha\Model\Article. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
218
            $handle = opendir($this->record->getAttachmentsLocation());
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Alpha\Model\ActiveRecord as the method getAttachmentsLocation() does only exist in the following sub-classes of Alpha\Model\ActiveRecord: Alpha\Model\Article. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
219
220
            $fileCount = 0;
221
222
            $html .= '<table class="table table-bordered">';
223
224
            // loop over the attachments directory
225
            while (false !== ($file = readdir($handle))) {
226
                if ($file != '.' && $file != '..') {
227
                    ++$fileCount;
228
229
                    $html .= '<tr>';
230
231
                    $html .= '<td>'.$file.' <em>('.number_format(filesize($this->record->getAttachmentsLocation().'/'.$file)/1024).' KB)</em></td>';
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Alpha\Model\ActiveRecord as the method getAttachmentsLocation() does only exist in the following sub-classes of Alpha\Model\ActiveRecord: Alpha\Model\Article. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
232
233
                    $js = "if(window.jQuery) {
234
                            BootstrapDialog.show({
235
                                title: 'Confirmation',
236
                                message: 'Are you sure you wish to delete this item?',
237
                                buttons: [
238
                                    {
239
                                        icon: 'glyphicon glyphicon-remove',
240
                                        label: 'Cancel',
241
                                        cssClass: 'btn btn-default btn-xs',
242
                                        action: function(dialogItself){
243
                                            dialogItself.close();
244
                                        }
245
                                    },
246
                                    {
247
                                        icon: 'glyphicon glyphicon-ok',
248
                                        label: 'Okay',
249
                                        cssClass: 'btn btn-default btn-xs',
250
                                        action: function(dialogItself) {
251
                                            $('[id=\"".($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('deletefile')) : 'deletefile')."\"]').attr('value', '".$file."');
252
                                            $('[id=\"".stripslashes(get_class($this->record)).'_'.$this->record->getID()."\"]').submit();
253
                                            dialogItself.close();
254
                                        }
255
                                    }
256
                                ]
257
                            });
258
                        }";
259
                    $button = new Button($js, 'Delete', 'delete'.$fileCount.'But');
260
                    $html .= '<td>'.$button->render().'</td>';
261
                    $html .= '</tr>';
262
                }
263
            }
264
265
            $html .= '</table>';
266
        } else {
267
            // we will take this opportunity to create the attachments folder is it does
268
            // not already exist.
269
            $this->record->createAttachmentsFolder();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Alpha\Model\ActiveRecord as the method createAttachmentsFolder() does only exist in the following sub-classes of Alpha\Model\ActiveRecord: Alpha\Model\Article. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
270
        }
271
272
        $html .= '<span class="btn btn-default btn-file">';
273
        $html .= '<input name="userfile" type="file" value="Browse..."/>';
274
        $html .= '</span>';
275
276
        $temp = new Button('submit', 'Upload', 'uploadBut');
277
        $html .= $temp->render();
278
279
        $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('deletefile')) : 'deletefile');
280
        $html .= '<input type="hidden" name="'.$fieldname.'" id="'.$fieldname.'" value=""/>';
281
282
        $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt('articleID')) : 'articleID');
283
        $html .= '<input type="hidden" name="'.$fieldname.'" id="'.$fieldname.'" value="'.$this->record->getID().'"/>';
284
285
        $html .= '</div>';
286
287
        return $html;
288
    }
289
}
290