Completed
Branch master (e8947e)
by Andreas
15:09
created

midgard_admin_asgard_handler_welcome   D

Complexity

Total Complexity 51

Size/Duplication

Total Lines 343
Duplicated Lines 12.54 %

Coupling/Cohesion

Components 1
Dependencies 18

Importance

Changes 0
Metric Value
dl 43
loc 343
rs 4.6563
c 0
b 0
f 0
wmc 51
lcom 1
cbo 18

8 Methods

Rating   Name   Duplication   Size   Complexity  
C _list_revised() 0 77 13
C _handler_welcome() 0 63 12
B _load_activities() 0 35 5
C _prepare_tabledata() 0 46 7
A _populate_toolbar() 0 49 2
B _mass_delete() 22 22 5
B _mass_approve() 21 21 5
A _show_welcome() 0 7 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like midgard_admin_asgard_handler_welcome often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use midgard_admin_asgard_handler_welcome, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * @package midgard.admin.asgard
4
 * @author The Midgard Project, http://www.midgard-project.org
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
/**
10
 * Welcome interface
11
 *
12
 * @package midgard.admin.asgard
13
 */
14
class midgard_admin_asgard_handler_welcome extends midcom_baseclasses_components_handler
1 ignored issue
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
15
{
16
    private function _list_revised($since, $review_by = null, $type = null, $only_mine = false)
17
    {
18
        $classes = array();
19
        $revised = array();
20
21
        // List installed MgdSchema types and convert to DBA classes
22
        foreach ($this->_request_data['schema_types'] as $schema_type)
23
        {
24
            if (   !is_null($type)
25
                && $schema_type != $type)
26
            {
27
                // Skip
28
                continue;
29
            }
30
31
            $mgdschema_class = midcom_helper_reflector::class_rewrite($schema_type);
32
            $dummy_object = new $mgdschema_class();
33
            $midcom_dba_classname = midcom::get()->dbclassloader->get_midcom_class_name_for_mgdschema_object($dummy_object);
34
            if (empty($midcom_dba_classname))
35
            {
36
                continue;
37
            }
38
39
            $classes[] = $midcom_dba_classname;
40
        }
41
42
        // List all revised objects
43
        foreach ($classes as $class)
44
        {
45
            if (!midcom::get()->dbclassloader->load_mgdschema_class_handler($class))
46
            {
47
                // Failed to load handling component, skip
48
                continue;
49
            }
50
            $qb_callback = array($class, 'new_query_builder');
51
            $qb = call_user_func($qb_callback);
52
53
            if ($since != 'any')
54
            {
55
                $qb->add_constraint('metadata.revised', '>=', $since);
56
            }
57
58
            if (   $only_mine
59
                && midcom::get()->auth->user)
60
            {
61
                $qb->add_constraint('metadata.authors', 'LIKE', '|' . midcom::get()->auth->user->guid . '|');
62
            }
63
64
            $qb->add_order('metadata.revision', 'DESC');
65
            $objects = $qb->execute();
66
67
            foreach ($objects as $object)
68
            {
69
                if (!is_null($review_by))
70
                {
71
                    $object_review_by = (int) $object->get_parameter('midcom.helper.metadata', 'review_date');
72
                    if ($object_review_by > $review_by)
73
                    {
74
                        // Skip
75
                        continue;
76
                    }
77
                }
78
79
                $revisor = midcom::get()->auth->get_user($object->metadata->revisor);
80
81
                $revised["{$object->metadata->revised}_{$object->guid}_{$object->metadata->revision}"] = array
82
                (
83
                    'object' => $object,
84
                    'revisor' => $revisor
85
                );
86
            }
87
        }
88
89
        krsort($revised);
90
91
        return $revised;
92
    }
93
94
    /**
95
     * Object editing view
96
     *
97
     * @param mixed $handler_id The ID of the handler.
98
     * @param array $args The argument list.
99
     * @param array &$data The local request data.
100
     */
101
    public function _handler_welcome($handler_id, array $args, array &$data)
0 ignored issues
show
Coding Style introduced by
_handler_welcome 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...
Coding Style introduced by
_handler_welcome uses the super-global variable $_REQUEST 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...
102
    {
103
        $data['schema_types'] = array_diff(midcom_connection::get_schema_types(), $this->_config->get('skip_in_filter'));
104
105
        $data['view_title'] = $this->_l10n->get('asgard');
106
107
        if (isset($_POST['execute_mass_action']))
108
        {
109
            if (   !empty($_POST['selections'])
110
                && isset($_POST['mass_action']))
111
            {
112
                $method_name = "_mass_{$_POST['mass_action']}";
113
                $this->$method_name($_POST['selections']);
114
            }
115
        }
116
117
        $data['revised'] = array();
118
        if (isset($_REQUEST['revised_after']))
119
        {
120
            $data['revised_after'] = $_REQUEST['revised_after'];
121
            if ($data['revised_after'] != 'any')
122
            {
123
                $data['revised_after'] = date('Y-m-d H:i:s\Z', $_REQUEST['revised_after']);
124
            }
125
126
            $data['review_by'] = null;
127
            if (   $this->_config->get('enable_review_dates')
128
                && isset($_REQUEST['review_by'])
129
                && $_REQUEST['review_by'] != 'any')
130
            {
131
                $data['review_by'] = (int) $_REQUEST['review_by'];
132
            }
133
134
            $data['type_filter'] = null;
135
            if (   isset($_REQUEST['type_filter'])
136
                && $_REQUEST['type_filter'] != 'any')
137
            {
138
                $data['type_filter'] = $_REQUEST['type_filter'];
139
            }
140
141
            $data['only_mine'] = !empty($_REQUEST['only_mine']);
142
143
            $objects = $this->_list_revised($data['revised_after'], $data['review_by'], $data['type_filter'], $data['only_mine']);
144
        }
145
        else if (class_exists('midcom_helper_activitystream_activity_dba'))
146
        {
147
            $objects = $this->_load_activities();
148
        }
149
        else
150
        {
151
            $data['revised_after'] = date('Y-m-d H:i:s\Z', mktime(0, 0, 0, date('m'), date('d') - 1, date('Y')));
152
            $objects = $this->_list_revised($data['revised_after']);
153
        }
154
155
        $this->_prepare_tabledata($objects);
156
157
        midcom::get()->head->add_jsfile(MIDCOM_STATIC_URL . '/jQuery/jquery.tablesorter.pack.js');
158
        midcom::get()->head->add_jsfile(MIDCOM_STATIC_URL . '/midgard.admin.asgard/jquery.batch_process.js');
159
        $this->add_stylesheet(MIDCOM_STATIC_URL . '/midgard.admin.asgard/tablewidget.css');
160
161
        $this->_populate_toolbar();
162
        return new midgard_admin_asgard_response($this, '_show_welcome');
163
    }
164
165
    private function _load_activities()
166
    {
167
        $objects = array();
168
        $activities = midcom_helper_activitystream_activity_dba::get($this->_config->get('last_visited_size'));
169
        foreach ($activities as $activity)
170
        {
171
            try
172
            {
173
                $object = midcom::get()->dbfactory->get_object_by_guid($activity->target);
174
            }
175
            catch (midcom_error $e)
176
            {
177
                if (midcom_connection::get_error() == MGD_ERR_OBJECT_DELETED)
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
178
                {
179
                    // TODO: Visualize deleted objects somehow
180
                }
181
                continue;
182
            }
183
            try
184
            {
185
                $actor = midcom_db_person::get_cached($activity->actor);
186
            }
187
            catch (midcom_error $e)
188
            {
189
                $actor = null;
190
            }
191
192
            $objects[] = array
193
            (
194
                'object' => $object,
195
                'revisor' => $actor
196
            );
197
        }
198
        return $objects;
199
    }
200
201
    private function _prepare_tabledata(array $objects)
202
    {
203
        $this->_request_data['revised'] = array();
204
        foreach ($objects as $data)
205
        {
206
            $object = $data['object'];
207
            $reflector = midcom_helper_reflector::get($object);
208
209
            $row = array
210
            (
211
                'icon' => $reflector->get_object_icon($object),
212
                'revision' => $object->metadata->revision,
213
                'revised' => $object->metadata->revised,
214
                'guid' => $object->guid,
215
                'class' => get_class($object)
216
            );
217
218
            $row['approved'] = ($object->is_approved()) ? strftime('%x %X', $object->metadata->approved) : $this->_l10n->get('not approved');
219
220
            $title = substr($reflector->get_object_label($object), 0, 60);
221
            $row['title'] = ($title) ?: '[' . $this->_l10n->get('no title') . ']';
222
223
            if (empty($data['revisor']))
224
            {
225
                $row['revisor'] = $this->_l10n_midcom->get('unknown');
226
            }
227
            else
228
            {
229
                $row['revisor'] = $data['revisor']->name;
230
            }
231
232
            if ($this->_config->get('enable_review_dates'))
233
            {
234
                $review_date = $object->get_parameter('midcom.helper.metadata', 'review_date');
235
                if (!$review_date)
236
                {
237
                    $row['review_date'] = $this->_l10n->get('n/a');
238
                }
239
                else
240
                {
241
                    $row['review_date'] = strftime('%x', $review_date);
242
                }
243
            }
244
            $this->_request_data['revised'][] = $row;
245
        }
246
    }
247
248
    private function _populate_toolbar()
249
    {
250
        $buttons = array();
251
        $buttons[] = array
252
        (
253
            MIDCOM_TOOLBAR_URL => '__mfa/asgard/preferences/',
254
            MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('user preferences'),
255
            MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/configuration.png',
256
        );
257
258
        if (midcom::get()->auth->admin)
259
        {
260
            $buttons[] = array
261
            (
262
                MIDCOM_TOOLBAR_URL => '__mfa/asgard/shell/',
263
                MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('shell'),
264
                MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/properties.png',
265
            );
266
            $buttons[] = array
267
            (
268
                MIDCOM_TOOLBAR_URL => '__mfa/asgard/trash/',
269
                MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('trash'),
270
                MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/trash-full.png',
271
            );
272
        }
273
274
        $buttons[] = array
275
        (
276
            MIDCOM_TOOLBAR_URL => '__mfa/asgard/components/',
277
            MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('components'),
278
            MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/component.png',
279
        );
280
281
        // Add link to site
282
        $buttons[] = array
283
        (
284
            MIDCOM_TOOLBAR_URL => midcom_core_context::get()->get_key(MIDCOM_CONTEXT_ANCHORPREFIX),
285
            MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('back to site'),
286
            MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/gohome.png',
287
        );
288
289
        $buttons[] = array
290
        (
291
            MIDCOM_TOOLBAR_URL => midcom_core_context::get()->get_key(MIDCOM_CONTEXT_ANCHORPREFIX) . "midcom-logout-",
292
            MIDCOM_TOOLBAR_LABEL => $this->_l10n_midcom->get('logout'),
293
            MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/exit.png',
294
        );
295
        $this->_request_data['asgard_toolbar']->add_items($buttons);
296
    }
297
298 View Code Duplication
    private function _mass_delete($guids)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
299
    {
300
        foreach ($guids as $guid)
301
        {
302
            try
303
            {
304
                $object = midcom::get()->dbfactory->get_object_by_guid($guid);
305
            }
306
            catch (midcom_error $e)
307
            {
308
                continue;
309
            }
310
311
            if ($object->can_do('midgard:delete'))
312
            {
313
                if ($object->delete())
314
                {
315
                    midcom::get()->uimessages->add($this->_l10n->get('midgard.admin.asgard'), sprintf($this->_l10n->get('object %s removed'), $object->guid));
316
                }
317
            }
318
        }
319
    }
320
321 View Code Duplication
    private function _mass_approve($guids)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
322
    {
323
        foreach ($guids as $guid)
324
        {
325
            try
326
            {
327
                $object = midcom::get()->dbfactory->get_object_by_guid($guid);
328
            }
329
            catch (midcom_error $e)
330
            {
331
                continue;
332
            }
333
334
            if (   $object->can_do('midgard:update')
335
                && $object->can_do('midcom:approve'))
336
            {
337
                $object->metadata->approve();
338
                midcom::get()->uimessages->add($this->_l10n->get('midgard.admin.asgard'), sprintf($this->_l10n->get('object %s approved'), $object->guid));
339
            }
340
        }
341
    }
342
343
    /**
344
     * Shows the loaded object in editor.
345
     *
346
     * @param mixed $handler_id The ID of the handler.
347
     * @param array &$data The local request data.
348
     */
349
    public function _show_welcome($handler_id, array &$data)
350
    {
351
        if (midcom::get()->auth->can_user_do('midgard.admin.asgard:manage_objects', null, 'midgard_admin_asgard_plugin'))
352
        {
353
            midcom_show_style('midgard_admin_asgard_welcome');
354
        }
355
    }
356
}
357