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

net_nemein_wiki_handler_edit   C

Complexity

Total Complexity 17

Size/Duplication

Total Lines 166
Duplicated Lines 6.63 %

Coupling/Cohesion

Components 1
Dependencies 19

Importance

Changes 0
Metric Value
dl 11
loc 166
rs 6.875
c 0
b 0
f 0
wmc 17
lcom 1
cbo 19

5 Methods

Rating   Name   Duplication   Size   Complexity  
A _load_schemadb() 0 13 2
B _handler_edit() 0 41 5
B add_preview() 0 37 6
A _handler_change() 0 16 2
A _load_controller() 11 11 2

How to fix   Duplicated Code   

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:

1
<?php
2
/**
3
 * @package net.nemein.wiki
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
 * Wikipage edit handler
11
 *
12
 * @package net.nemein.wiki
13
 */
14
class net_nemein_wiki_handler_edit 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
    /**
17
     * The wikipage we're editing
18
     *
19
     * @var net_nemein_wiki_wikipage
20
     */
21
    private $_page = null;
22
23
    /**
24
     * The Controller of the article used for editing
25
     *
26
     * @var midcom_helper_datamanager2_controller_simple
27
     */
28
    private $_controller = null;
29
30
    /**
31
     * The schema database in use, available only while a datamanager is loaded.
32
     *
33
     * @var Array
34
     */
35
    private $_schemadb = null;
36
37
    /**
38
     * Loads and prepares the schema database.
39
     *
40
     * The operations are done on all available schemas within the DB.
41
     */
42
    private function _load_schemadb()
43
    {
44
        $this->_schemadb = midcom_helper_datamanager2_schema::load_database($this->_config->get('schemadb'));
45
46
        $operations = array();
47
        $operations['save'] = '';
48
        $operations['preview'] = $this->_l10n->get('preview');
49
        $operations['cancel'] = '';
50
        foreach ($this->_schemadb as $schema)
51
        {
52
            $schema->operations = $operations;
53
        }
54
    }
55
56
    /**
57
     * Internal helper, loads the controller for the current article. Any error triggers a 500.
58
     */
59 View Code Duplication
    private function _load_controller()
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...
60
    {
61
        $this->_load_schemadb();
62
        $this->_controller = midcom_helper_datamanager2_controller::create('simple');
63
        $this->_controller->schemadb =& $this->_schemadb;
64
        $this->_controller->set_storage($this->_page);
65
        if (! $this->_controller->initialize())
66
        {
67
            throw new midcom_error("Failed to initialize a DM2 controller instance for article {$this->_article->id}.");
68
        }
69
    }
70
71
    /**
72
     * Check the edit request
73
     *
74
     * @param mixed $handler_id The ID of the handler.
75
     * @param array $args The argument list.
76
     * @param array &$data The local request data.
77
     */
78
    public function _handler_edit($handler_id, array $args, array &$data)
79
    {
80
        $this->_page = $this->_master->load_page($args[0]);
81
        $this->_page->require_do('midgard:update');
82
83
        $this->_load_controller();
84
85
        midcom::get()->head->set_pagetitle(sprintf($this->_l10n->get('edit %s'), $this->_page->title));
86
87
        $workflow = $this->get_workflow('datamanager2', array
88
        (
89
            'controller' => $this->_controller,
90
            'save_callback' => array($this, 'save_callback')
91
        ));
92
93
        foreach (array_keys($this->_request_data['schemadb']) as $name)
94
        {
95
            if ($name == $this->_controller->datamanager->schema->name)
96
            {
97
                // The page is already of this type, skip
98
                continue;
99
            }
100
            $label = sprintf($this->_l10n->get('change to %s'), $this->_l10n->get($data['schemadb'][$name]->description));
101
            $workflow->add_post_button("change/{$this->_page->name}/", $label, array('change_to' => $name));
102
        }
103
104
        $response = $workflow->run();
105
106
        if ($workflow->get_state() == 'preview')
107
        {
108
            $this->add_preview();
109
        }
110
        else if ($workflow->get_state() == 'save')
111
        {
112
            $indexer = midcom::get()->indexer;
113
            net_nemein_wiki_viewer::index($this->_controller->datamanager, $indexer, $this->_topic);
114
            midcom::get()->uimessages->add($this->_l10n->get($this->_component), sprintf($this->_l10n->get('page %s saved'), $this->_page->title));
115
        }
116
117
        return $response;
118
    }
119
120
    private function add_preview()
121
    {
122
        $preview_page = $this->_page;
123
        foreach ($this->_controller->datamanager->schema->fields as $name => $type_definition)
124
        {
125
            if (!is_a($this->_controller->datamanager->types[$name], 'midcom_helper_datamanager2_type_text'))
126
            {
127
                // Skip fields of other types
128
                continue;
129
            }
130
            switch ($type_definition['storage'])
131
            {
132
                case 'parameter':
133
                case 'configuration':
134
                case 'metadata':
135
                    // Skip
136
                    continue;
137
                default:
138
                    $location = $type_definition['storage']['location'];
139
            }
140
            $preview_page->$location = $this->_controller->datamanager->types[$name]->convert_to_storage();
0 ignored issues
show
Bug introduced by
The variable $location 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...
141
        }
142
143
        // Load DM for rendering the page
144
        $datamanager = new midcom_helper_datamanager2_datamanager($this->_schemadb);
145
        $datamanager->autoset_storage($preview_page);
146
        $wikipage_view = $datamanager->get_content_html();
147
        // Replace wikiwords
148
        // TODO: We should somehow make DM2 do this so it would also work in AJAX previews
149
        $parser = new net_nemein_wiki_parser($preview_page);
150
        $preview = $parser->get_markdown($wikipage_view['content']);
151
152
        $form = $this->_controller->formmanager->form;
153
        $form->addElement('static', 'preview', $this->_l10n->get('preview'), '<div class="wiki_preview">' . $preview . '</div>');
154
        $element = array_pop($form->_elements);
155
        array_unshift($form->_elements, $element);
156
    }
157
158
    /**
159
     * @param mixed $handler_id The ID of the handler.
160
     * @param array $args The argument list.
161
     * @param array &$data The local request data.
162
     */
163
    public function _handler_change($handler_id, array $args, array &$data)
0 ignored issues
show
Coding Style introduced by
_handler_change 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...
164
    {
165
        if (empty($_POST['change_to']))
166
        {
167
            throw new midcom_error_forbidden('Only POST requests are allowed here.');
168
        }
169
170
        $this->_page = $this->_master->load_page($args[0]);
171
        $this->_page->require_do('midgard:update');
172
173
        // Change schema to redirect
174
        $this->_page->set_parameter('midcom.helper.datamanager2', 'schema_name', $_POST['change_to']);
175
176
        // Redirect to editing
177
        return new midcom_response_relocate("edit/{$this->_page->name}/");
178
    }
179
}
180