Passed
Push — master ( b54d6e...32f105 )
by Andreas
34:18
created

org_openpsa_relatedto_plugin   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 255
Duplicated Lines 0 %

Test Coverage

Coverage 56.92%

Importance

Changes 0
Metric Value
eloc 139
dl 0
loc 255
ccs 74
cts 130
cp 0.5692
rs 9.52
c 0
b 0
f 0
wmc 36

8 Methods

Rating   Name   Duplication   Size   Complexity  
A add_button() 0 6 1
A common_node_toolbar_buttons_sanitycheck() 0 32 5
A common_toolbar_buttons_defaults() 0 19 1
A add_journal_entry_button() 0 6 1
C common_node_toolbar_buttons() 0 68 12
A relatedto2get() 0 24 5
B create() 0 35 6
A get2relatedto() 0 17 5
1
<?php
2
/**
3
 * @package org.openpsa.relatedto
4
 * @author Nemein Oy, http://www.nemein.com/
5
 * @copyright Nemein Oy, http://www.nemein.com/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
/**
10
 * Class for handling "related to" information
11
 *
12
 * @package org.openpsa.relatedto
13
 */
14
class org_openpsa_relatedto_plugin extends midcom_baseclasses_components_plugin
15
{
16
    /**
17
     * Shorthand for creating a relatedto object.
18
     *
19
     * The <i>from</i> object is something that is related to the <em>to</em>
20
     * object.
21
     * For example, if a task is created under a sales project, that task is
22
     * the from object, and the sales project the to object.
23
     *
24
     * @param object $from_obj The from object
25
     * @param string $from_component The from component name
26
     * @param object $to_obj The to object
27
     * @param string $to_component The to component name
28
     * @param int $status The status of the relation
29
     * @param array $extra Array with the possible extra-properties
30
     * @return mixed The newly-created relatedto object or false on failure
31
     */
32 11
    public static function create(object $from_obj, string $from_component, object $to_obj, string $to_component, int $status = null, array $extra = []) : ?org_openpsa_relatedto_dba
33
    {
34 11
        if (!$status) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $status of type integer|null is loosely compared to false; this is ambiguous if the integer can be 0. 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 integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
35 11
            $status = org_openpsa_relatedto_dba::CONFIRMED;
36
        }
37
38 11
        $rel = new org_openpsa_relatedto_dba();
39 11
        $rel->fromClass = get_class($from_obj);
40 11
        $rel->toClass = get_class($to_obj);
41 11
        $rel->fromGuid = $from_obj->guid;
42 11
        $rel->toGuid = $to_obj->guid;
43 11
        $rel->fromComponent = $from_component;
44 11
        $rel->toComponent = $to_component;
45 11
        $rel->status = $status;
46
47 11
        if ($guid = $rel->check_db(false)) {
48 1
            $db_rel = new org_openpsa_relatedto_dba($guid);
49 1
            debug_add("A relation from {$rel->fromClass} #{$rel->fromGuid} to {$rel->toClass} #{$rel->toGuid} already exists, returning this one instead");
50 1
            if ($db_rel->status < $rel->status) {
51 1
                $db_rel->status = $rel->status;
52 1
                $db_rel->update();
53
            }
54 1
            return $db_rel;
55
        }
56
57 11
        foreach ($extra as $extra_key => $extra_value) {
58
            $rel->$extra_key = $extra_value;
59
        }
60
61 11
        if (!$rel->create()) {
62
            debug_add("failed to create link from {$rel->fromClass} #{$rel->fromGuid} to {$rel->toClass} #{$rel->toGuid}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_WARN);
63
            return null;
64
        }
65
66 11
        return $rel;
67
    }
68
69
    /**
70
     * Parses relatedto information from request, returning either
71
     * existing matching relatedtos or prefilled new ones for creation
72
     */
73 31
    public static function get2relatedto() : array
74
    {
75 31
        $ret = [];
76 31
        if (!array_key_exists('org_openpsa_relatedto', $_REQUEST)) {
77 31
            return $ret;
78
        }
79
        foreach ($_REQUEST['org_openpsa_relatedto'] as $rel_array) {
80
            $rel = new org_openpsa_relatedto_dba();
81
            foreach ($rel_array as $k => $v) {
82
                $rel->$k = $v;
83
            }
84
            if ($guid = $rel->check_db()) {
85
                $rel = new org_openpsa_relatedto_dba($guid);
86
            }
87
            $ret[] = $rel;
88
        }
89
        return $ret;
90
    }
91
92
    /**
93
     * Serializes an array or relatedto objects into GET parameters
94
     *
95
     * NOTE: does not prefix the ? for the first parameter in case this needs
96
     * to be used with some other GET parameters.
97
     */
98 1
    public static function relatedto2get(array $array) : ?string
99
    {
100 1
        $ret = ['org_openpsa_relatedto' => []];
101 1
        foreach ($array as $rel) {
102 1
            if (!midcom::get()->dbfactory->is_a($rel, org_openpsa_relatedto_dba::class)) { //Matches also 'org_openpsa_relatedto'
103
                //Wrong type of object found in array, cruelly abort the whole procedure
104
                return null;
105
            }
106
            $entry = [
107 1
                'toGuid' => $rel->toGuid,
108 1
                'toComponent' => $rel->toComponent,
109 1
                'toClass' => $rel->toClass
110
            ];
111
112
            //To save GET space we only append these if they have values
113 1
            foreach (['status', 'fromComponent', 'fromClass', 'fromGuid'] as $key) {
114 1
                if ($rel->$key) {
115 1
                    $entry[$key] = $rel->$key;
116
                }
117
            }
118
119 1
            $ret['org_openpsa_relatedto'][] = $entry;
120
        }
121 1
        return http_build_query($ret, '', '&');
122
    }
123
124 4
    public static function add_button(midcom_helper_toolbar $toolbar, string $guid)
125
    {
126 4
        $toolbar->add_item([
127 4
            MIDCOM_TOOLBAR_URL => "__mfa/org.openpsa.relatedto/render/{$guid}/both/",
128 4
            MIDCOM_TOOLBAR_LABEL => midcom::get()->i18n->get_string('view related information', 'org.openpsa.relatedto'),
129 4
            MIDCOM_TOOLBAR_GLYPHICON => 'paperclip',
130
        ]);
131 4
    }
132
133 5
    private static function common_node_toolbar_buttons_sanitycheck(array &$data, string $button_component, $bind_object, string $calling_component) : ?org_openpsa_relatedto_dba
134
    {
135 5
        if (!midcom::get()->componentloader->is_installed($button_component)) {
136
            debug_add("component {$button_component} is not installed", MIDCOM_LOG_ERROR);
137
            return null;
138
        }
139 5
        if (empty($data['node'])) {
140 5
            debug_add("data['node'] not given, trying with siteconfig");
141 5
            $siteconfig = org_openpsa_core_siteconfig::get_instance();
142 5
            $node_guid = $siteconfig->get_node_guid($button_component);
143 5
            if (!$node_guid) {
144
                debug_add("data['node'] not given, and {$button_component} could not be found in siteconfig", MIDCOM_LOG_INFO);
145
                return null;
146
            }
147
148 5
            $nap = new midcom_helper_nav();
149 5
            $data['node'] = $nap->resolve_guid($node_guid);
150 5
            if (empty($data['node'])) {
151
                //Invalid node given/found
152 5
                debug_add("data['node'] is invalid", MIDCOM_LOG_ERROR);
153 5
                return null;
154
            }
155
        }
156
157
        $related_to = new org_openpsa_relatedto_dba();
158
        $related_to->toGuid = $bind_object->guid;
159
        $related_to->toClass = get_class($bind_object);
160
        $related_to->toComponent = $calling_component;
161
        $related_to->fromComponent = $button_component;
162
        $related_to->status = org_openpsa_relatedto_dba::CONFIRMED;
163
164
        return $related_to;
165
    }
166
167 3
    public static function common_toolbar_buttons_defaults() : array
168
    {
169
        return [
170
            'event' => [
171 3
                'node' => false,
172
                'component' => 'org.openpsa.calendar'
173
            ],
174
            'task'  => [
175
                'node' => false,
176
                'component' => 'org.openpsa.projects'
177
            ],
178
            'wikinote' => [
179
                'node' => false,
180
                'component' => 'net.nemein.wiki',
181
                'wikiword'  => false, //Calling component MUST define this key to get a wikinote button
182
            ],
183
            'document' => [
184
                'node' => false,
185
                'component' => 'org.openpsa.documents'
186
            ],
187
        ];
188
    }
189
190 5
    public static function common_node_toolbar_buttons(midcom_helper_toolbar $toolbar, $bind_object, string $calling_component, array $buttons)
191
    {
192 5
        $workflow = new midcom\workflow\datamanager;
193 5
        $toolbar_buttons = [];
194 5
        foreach ($buttons as $mode => $data) {
195 5
            debug_print_r("processing button '{$mode}' with data:", $data);
196 5
            if ($data === false) {
197
                //In case somebody didn't unset() a button from the defaults, just marked it as false
198
                debug_add('data marked as false, skipping (the correct way is to unset() the key)', MIDCOM_LOG_WARN);
199
                continue;
200
            }
201
202 5
            $related_to = self::common_node_toolbar_buttons_sanitycheck($data, $data['component'], $bind_object, $calling_component);
203 5
            if (!$related_to) {
204 5
                debug_add("sanitycheck returned false, skipping", MIDCOM_LOG_WARN);
205 5
                continue;
206
            }
207
            //Remember that switch is also a for statement in PHPs mind, use "continue 2"
208
            switch ($mode) {
209
                case 'event':
210
                    $toolbar_buttons[] = org_openpsa_calendar_interface::get_create_button($data['node'], '?' . self::relatedto2get([$related_to]));
211
                    break;
212
                case 'task':
213
                    if (midcom::get()->auth->can_user_do('midgard:create', null, org_openpsa_projects_task_dba::class)) {
214
                        $toolbar_buttons[] = $workflow->get_button("{$data['node'][MIDCOM_NAV_ABSOLUTEURL]}task/new/?" . self::relatedto2get([$related_to]), [
215
                            MIDCOM_TOOLBAR_LABEL => midcom::get()->i18n->get_string('create task', $data['component']),
216
                            MIDCOM_TOOLBAR_GLYPHICON => 'calendar-check-o',
217
                            MIDCOM_TOOLBAR_OPTIONS => ['data-refresh-opener' => 'true'],
218
                        ]);
219
                    }
220
                    break;
221
                case 'wikinote':
222
                    if (empty($data['wikiword'])) {
223
                        //Wikiword to use not given
224
                        debug_add("data['wikiword'] not given, skipping", MIDCOM_LOG_WARN);
225
                        continue 2;
226
                    }
227
228
                    if (!net_nemein_wiki_interface::node_wikiword_is_free($data['node'], $data['wikiword'])) {
229
                        //Wikiword is already reserved
230
                        //PONDER: append number or something and check again ??
231
                        debug_add("node_wikiword_is_free returned false for '{$data['wikiword']}'", MIDCOM_LOG_WARN);
232
                        continue 2;
233
                    }
234
235
                    $data['wikiword_encoded'] = rawurlencode($data['wikiword']);
236
                    $toolbar_buttons[] = $workflow->get_button("{$data['node'][MIDCOM_NAV_ABSOLUTEURL]}create/?wikiword={$data['wikiword_encoded']}&" . self::relatedto2get([$related_to]), [
237
                        MIDCOM_TOOLBAR_LABEL => midcom::get()->i18n->get_string('create note', $data['component']),
238
                        MIDCOM_TOOLBAR_GLYPHICON => 'sticky-note-o',
239
                        MIDCOM_TOOLBAR_ENABLED => $data['node'][MIDCOM_NAV_OBJECT]->can_do('midgard:create'),
240
                        MIDCOM_TOOLBAR_OPTIONS => ['data-refresh-opener' => 'true'],
241
                    ]);
242
                    break;
243
                case 'document':
244
                    if ($data['node'][MIDCOM_NAV_OBJECT]->can_do('midgard:create')) {
245
                        $toolbar_buttons[] = $workflow->get_button("{$data['node'][MIDCOM_NAV_ABSOLUTEURL]}document/create/?" . self::relatedto2get([$related_to]), [
246
                            MIDCOM_TOOLBAR_LABEL => midcom::get()->i18n->get_string('create document', $data['component']),
247
                            MIDCOM_TOOLBAR_GLYPHICON => 'file-o',
248
                            MIDCOM_TOOLBAR_OPTIONS => ['data-refresh-opener' => 'true'],
249
                        ]);
250
                    }
251
                    break;
252
                default:
253
                    debug_add("given button '{$mode}' not recognized", MIDCOM_LOG_ERROR);
254
                    break;
255
            }
256
        }
257 5
        $toolbar->add_items($toolbar_buttons);
258 5
    }
259
260
    /**
261
     * function to add the button for journal_entry to the toolbar
262
     */
263 2
    public static function add_journal_entry_button(midcom_helper_toolbar $toolbar, string $guid)
264
    {
265 2
        $toolbar->add_item([
266 2
            MIDCOM_TOOLBAR_URL => "__mfa/org.openpsa.relatedto/journalentry/{$guid}/",
267 2
            MIDCOM_TOOLBAR_LABEL => midcom::get()->i18n->get_string('view journal entries', 'org.openpsa.relatedto'),
268 2
            MIDCOM_TOOLBAR_GLYPHICON => 'list',
269
        ]);
270 2
    }
271
}
272