Completed
Push — master ( 01ca5d...148252 )
by Andreas
17:12
created

org_openpsa_relatedto_plugin::create()   B

Complexity

Conditions 8
Paths 13

Size

Total Lines 40
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 8.0877

Importance

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