GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (4873)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

plugins/tracker/include/trackerPlugin.class.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Copyright (c) Enalean, 2011. All Rights Reserved.
4
 *
5
 * Tuleap is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * Tuleap is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with Tuleap; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19
20
require_once('common/plugin/Plugin.class.php');
21
require_once 'constants.php';
22
require_once 'autoload.php';
23
24
/**
25
 * trackerPlugin
26
 */
27
class trackerPlugin extends Plugin {
28
29
    const EMAILGATEWAY_TOKEN_ARTIFACT_UPDATE      = 'forge__artifacts';
30
    const EMAILGATEWAY_INSECURE_ARTIFACT_CREATION = 'forge__tracker';
31
    const EMAILGATEWAY_INSECURE_ARTIFACT_UPDATE   = 'forge__artifact';
32
    const SERVICE_SHORTNAME                       = 'plugin_tracker';
33
    const TRUNCATED_SERVICE_NAME                  = 'Trackers';
34
35
36
    public function __construct($id) {
37
        parent::__construct($id);
38
        $this->setScope(self::SCOPE_PROJECT);
39
40
        $this->_addHook('cssfile',                             'cssFile',                           false);
41
        $this->_addHook(Event::GET_AVAILABLE_REFERENCE_NATURE, 'get_available_reference_natures',   false);
42
        $this->_addHook(Event::GET_ARTIFACT_REFERENCE_GROUP_ID,'get_artifact_reference_group_id',   false);
43
        $this->_addHook(Event::BUILD_REFERENCE,                'build_reference',                   false);
44
        $this->_addHook('ajax_reference_tooltip',              'ajax_reference_tooltip',            false);
45
        $this->_addHook(Event::SERVICE_CLASSNAMES,             'service_classnames',                false);
46
        $this->_addHook(Event::COMBINED_SCRIPTS,               'combined_scripts',                  false);
47
        $this->_addHook(Event::JAVASCRIPT,                     'javascript',                        false);
48
        $this->_addHook(Event::TOGGLE,                         'toggle',                            false);
49
        $this->_addHook(Event::SERVICE_PUBLIC_AREAS,           'service_public_areas',              false);
50
        $this->_addHook('permission_get_name',                 'permission_get_name',               false);
51
        $this->_addHook('permission_get_object_type',          'permission_get_object_type',        false);
52
        $this->_addHook('permission_get_object_name',          'permission_get_object_name',        false);
53
        $this->_addHook('permission_get_object_fullname',      'permission_get_object_fullname',    false);
54
        $this->_addHook('permission_user_allowed_to_change',   'permission_user_allowed_to_change', false);
55
        $this->_addHook('permissions_for_ugroup',              'permissions_for_ugroup',            false);
56
57
        $this->_addHook(Event::SYSTEM_EVENT_GET_CUSTOM_QUEUES);
58
        $this->_addHook(Event::SYSTEM_EVENT_GET_TYPES_FOR_CUSTOM_QUEUE);
59
        $this->_addHook(Event::GET_SYSTEM_EVENT_CLASS,         'getSystemEventClass',               false);
60
61
        $this->_addHook('url_verification_instance',           'url_verification_instance',         false);
62
63
        $this->addHook(Event::SERVICE_ICON);
64
        $this->addHook(Event::SERVICES_ALLOWED_FOR_PROJECT);
65
66
        $this->addHook('widget_instance');
67
        $this->addHook('widgets');
68
        $this->addHook('default_widgets_for_new_owner');
69
70
        $this->_addHook('project_is_deleted',                  'project_is_deleted',                false);
71
        $this->_addHook('register_project_creation',           'register_project_creation',         false);
72
        $this->_addHook('codendi_daily_start',                 'codendi_daily_start',               false);
73
        $this->_addHook('fill_project_history_sub_events',     'fillProjectHistorySubEvents',       false);
74
        $this->_addHook(Event::SOAP_DESCRIPTION,               'soap_description',                  false);
75
        $this->_addHook(Event::IMPORT_XML_PROJECT);
76
        $this->addHook(Event::USER_MANAGER_GET_USER_INSTANCE);
77
        $this->_addHook('plugin_statistics_service_usage');
78
        $this->addHook(Event::REST_RESOURCES);
79
        $this->addHook(Event::REST_GET_PROJECT_TRACKERS);
80
        $this->addHook(Event::REST_OPTIONS_PROJECT_TRACKERS);
81
        $this->addHook(Event::REST_PROJECT_RESOURCES);
82
83
        $this->addHook(Event::BACKEND_ALIAS_GET_ALIASES);
84
        $this->addHook(Event::GET_PROJECTID_FROM_URL);
85
        $this->addHook(Event::SITE_ADMIN_CONFIGURATION_TRACKER);
86
        $this->addHook(Event::EXPORT_XML_PROJECT);
87
        $this->addHook(Event::GET_REFERENCE);
88
        $this->addHook(Event::CAN_USER_ACCESS_UGROUP_INFO);
89
        $this->addHook(Event::SERVICES_TRUNCATED_EMAILS);
90
        $this->addHook('site_admin_option_hook');
91
    }
92
93
    public function getHooksAndCallbacks() {
94
        if (defined('AGILEDASHBOARD_BASE_DIR')) {
95
            $this->addHook(AGILEDASHBOARD_EVENT_ADDITIONAL_PANES_ON_MILESTONE);
96
            $this->addHook(AGILEDASHBOARD_EVENT_ADDITIONAL_PANES_INFO_ON_MILESTONE);
97
            $this->addHook(AGILEDASHBOARD_EXPORT_XML);
98
99
            // REST Milestones
100
            $this->addHook(AGILEDASHBOARD_EVENT_REST_GET_MILESTONE);
101
            $this->addHook(AGILEDASHBOARD_EVENT_REST_GET_BURNDOWN);
102
            $this->addHook(AGILEDASHBOARD_EVENT_REST_OPTIONS_BURNDOWN);
103
        }
104
        if (defined('STATISTICS_BASE_DIR')) {
105
            $this->addHook(Statistics_Event::FREQUENCE_STAT_ENTRIES);
106
            $this->addHook(Statistics_Event::FREQUENCE_STAT_SAMPLE);
107
        }
108
        if (defined('FULLTEXTSEARCH_BASE_URL')) {
109
            $this->_addHook(FULLTEXTSEARCH_EVENT_FETCH_ALL_DOCUMENT_SEARCH_TYPES);
110
            $this->_addHook(FULLTEXTSEARCH_EVENT_FETCH_PROJECT_TRACKER_FIELDS);
111
            $this->_addHook(FULLTEXTSEARCH_EVENT_DOES_TRACKER_SERVICE_USE_UGROUP);
112
        }
113
114
        return parent::getHooksAndCallbacks();
115
    }
116
117
    public function getPluginInfo() {
118
        if (!is_a($this->pluginInfo, 'trackerPluginInfo')) {
119
            include_once('trackerPluginInfo.class.php');
120
            $this->pluginInfo = new trackerPluginInfo($this);
121
        }
122
        return $this->pluginInfo;
123
    }
124
125
    /**
126
     * @see Statistics_Event::FREQUENCE_STAT_ENTRIES
127
     */
128
    public function plugin_statistics_frequence_stat_entries($params) {
129
        $params['entries'][$this->getServiceShortname()] = 'Opened artifacts';
130
    }
131
132
    /**
133
     * @see Statistics_Event::FREQUENCE_STAT_SAMPLE
134
     */
135
    public function plugin_statistics_frequence_stat_sample($params) {
136
        if ($params['character'] === $this->getServiceShortname()) {
137
            $params['sample'] = new Tracker_Sample();
138
        }
139
    }
140
141
    public function site_admin_option_hook($params) {
142
        $name = $GLOBALS['Language']->getText('plugin_tracker', 'descriptor_name');
143
144
        echo '<li><a href="'.$this->getPluginPath().'/config.php">'.$name.'</a></li>';
145
    }
146
147
    public function cssFile($params) {
148
        $include_tracker_css_file = false;
149
        EventManager::instance()->processEvent(TRACKER_EVENT_INCLUDE_CSS_FILE, array('include_tracker_css_file' => &$include_tracker_css_file));
150
        // Only show the stylesheet if we're actually in the tracker pages.
151
        // This stops styles inadvertently clashing with the main site.
152
        if ($include_tracker_css_file ||
153
            strpos($_SERVER['REQUEST_URI'], $this->getPluginPath()) === 0 ||
154
            strpos($_SERVER['REQUEST_URI'], '/my/') === 0 ||
155
            strpos($_SERVER['REQUEST_URI'], '/projects/') === 0 ||
156
            strpos($_SERVER['REQUEST_URI'], '/widgets/') === 0 ) {
157
            echo '<link rel="stylesheet" type="text/css" href="'.$this->getThemePath().'/css/style.css" />';
158
            echo '<link rel="stylesheet" type="text/css" href="'.$this->getThemePath().'/css/print.css" media="print" />';
159
            if (file_exists($this->getThemePath().'/css/ieStyle.css')) {
160
                echo '<!--[if lte IE 8]><link rel="stylesheet" type="text/css" href="'.$this->getThemePath().'/css/ieStyle.css" /><![endif]-->';
161
            }
162
        }
163
    }
164
165
    /**
166
     *This callback make SystemEvent manager knows about Tracker plugin System Events
167
     */
168
    public function getSystemEventClass($params) {
169
        switch($params['type']) {
170
            case SystemEvent_TRACKER_V3_MIGRATION::NAME:
171
                $params['class'] = 'SystemEvent_TRACKER_V3_MIGRATION';
172
                $params['dependencies'] = array(
173
                    $this->getMigrationManager(),
174
                );
175
                break;
176
            default:
177
                break;
178
        }
179
    }
180
181
    public function service_classnames($params) {
182
        include_once 'ServiceTracker.class.php';
183
        $params['classnames'][$this->getServiceShortname()] = 'ServiceTracker';
184
    }
185
186
    public function getServiceShortname() {
187
        return self::SERVICE_SHORTNAME;
188
    }
189
190
    public function combined_scripts($params) {
191
        $params['scripts'] = array_merge(
192
            $params['scripts'],
193
            array(
194
                '/plugins/tracker/scripts/TrackerReports.js',
195
                '/plugins/tracker/scripts/TrackerEmailCopyPaste.js',
196
                '/plugins/tracker/scripts/TrackerReportsSaveAsModal.js',
197
                '/plugins/tracker/scripts/TrackerBinds.js',
198
                '/plugins/tracker/scripts/ReorderColumns.js',
199
                '/plugins/tracker/scripts/TrackerTextboxLists.js',
200
                '/plugins/tracker/scripts/TrackerAdminFields.js',
201
                '/plugins/tracker/scripts/TrackerArtifact.js',
202
                '/plugins/tracker/scripts/TrackerArtifactEmailActions.js',
203
                '/plugins/tracker/scripts/TrackerArtifactLink.js',
204
                '/plugins/tracker/scripts/TrackerCreate.js',
205
                '/plugins/tracker/scripts/TrackerFormElementFieldPermissions.js',
206
                '/plugins/tracker/scripts/TrackerDateReminderForms.js',
207
                '/plugins/tracker/scripts/TrackerTriggers.js',
208
                '/plugins/tracker/scripts/SubmissionKeeper.js',
209
                '/plugins/tracker/scripts/TrackerFieldDependencies.js',
210
                '/plugins/tracker/scripts/TrackerRichTextEditor.js',
211
                '/plugins/tracker/scripts/artifactChildren.js',
212
                '/plugins/tracker/scripts/load-artifactChildren.js',
213
                '/plugins/tracker/scripts/modal-in-place.js',
214
                '/plugins/tracker/scripts/TrackerArtifactEditionSwitcher.js',
215
                '/plugins/tracker/scripts/FixAggregatesHeaderHeight.js',
216
                '/plugins/tracker/scripts/TrackerSettings.js',
217
                '/plugins/tracker/scripts/TrackerCollapseFieldset.js',
218
                '/plugins/tracker/scripts/TrackerArtifactReferences.js',
219
                '/plugins/tracker/scripts/CopyArtifact.js',
220
            )
221
        );
222
    }
223
224
    public function javascript($params) {
225
        // TODO: Move this in ServiceTracker::displayHeader()
226
        include $GLOBALS['Language']->getContent('script_locale', null, 'tracker');
227
        echo PHP_EOL;
228
        echo "codendi.tracker = codendi.tracker || { };".PHP_EOL;
229
        echo "codendi.tracker.base_url = '". TRACKER_BASE_URL ."/';".PHP_EOL;
230
    }
231
232
    public function toggle($params) {
233
        if ($params['id'] === 'tracker_report_query_0') {
234
            Toggler::togglePreference($params['user'], $params['id']);
235
            $params['done'] = true;
236
        } else if (strpos($params['id'], 'tracker_report_query_') === 0) {
237
            $report_id = (int)substr($params['id'], strlen('tracker_report_query_'));
238
            $report_factory = Tracker_ReportFactory::instance();
239
            if (($report = $report_factory->getReportById($report_id, $params['user']->getid())) && $report->userCanUpdate($params['user'])) {
240
                $report->toggleQueryDisplay();
241
                $report_factory->save($report);
242
            }
243
            $params['done'] = true;
244
        }
245
    }
246
247
    public function agiledashboard_event_additional_panes_on_milestone($params) {
248
        $user      = $params['user'];
249
        $milestone = $params['milestone'];
250
        $pane_info = $this->getPaneInfo($milestone, $user);
251
        if (! $pane_info) {
252
            return;
253
        }
254
255
        if ($params['request']->get('pane') == Tracker_Artifact_Burndown_PaneInfo::IDENTIFIER) {
256
            $pane_info->setActive(true);
257
            $artifact = $milestone->getArtifact();
258
            $params['active_pane'] = new Tracker_Artifact_Burndown_Pane(
259
                    $pane_info,
260
                    $artifact,
261
                    $artifact->getABurndownField($user),
262
                    $user
263
            );
264
        }
265
        $params['panes'][] = $pane_info;
266
    }
267
268
    public function agiledashboard_event_additional_panes_info_on_milestone($params) {
269
        $pane_info = $this->getPaneInfo($params['milestone'], $params['user']);
270
        if (! $pane_info) {
271
            return;
272
        }
273
274
        $params['pane_info_list'][] = $pane_info;
275
    }
276
277
    private function getPaneInfo($milestone, $user) {
278
        $artifact = $milestone->getArtifact();
279
        if (! $artifact->getABurndownField($user)) {
280
            return;
281
        }
282
283
        return new Tracker_Artifact_Burndown_PaneInfo($milestone);
284
    }
285
286
   /**
287
    * Project creation hook
288
    *
289
    * @param Array $params
290
    */
291
    function register_project_creation($params) {
292
        $tm = new TrackerManager();
293
        $tm->duplicate($params['template_id'], $params['group_id'], $params['ugroupsMapping']);
294
295
    }
296
297
    function permission_get_name($params) {
298
        if (!$params['name']) {
299
            switch($params['permission_type']) {
300
            case 'PLUGIN_TRACKER_FIELD_SUBMIT':
301
                $params['name'] = $GLOBALS['Language']->getText('plugin_tracker_permissions','plugin_tracker_field_submit');
302
                break;
303
            case 'PLUGIN_TRACKER_FIELD_READ':
304
                $params['name'] = $GLOBALS['Language']->getText('plugin_tracker_permissions','plugin_tracker_field_read');
305
                break;
306
            case 'PLUGIN_TRACKER_FIELD_UPDATE':
307
                $params['name'] = $GLOBALS['Language']->getText('plugin_tracker_permissions','plugin_tracker_field_update');
308
                break;
309
            case Tracker::PERMISSION_SUBMITTER_ONLY:
310
                $params['name'] = $GLOBALS['Language']->getText('plugin_tracker_permissions','plugin_tracker_submitter_only_access');
311
                break;
312
            case Tracker::PERMISSION_SUBMITTER:
313
                $params['name'] = $GLOBALS['Language']->getText('plugin_tracker_permissions','plugin_tracker_submitter_access');
314
                break;
315
            case Tracker::PERMISSION_ASSIGNEE:
316
                $params['name'] = $GLOBALS['Language']->getText('plugin_tracker_permissions','plugin_tracker_assignee_access');
317
                break;
318
            case Tracker::PERMISSION_FULL:
319
                $params['name'] = $GLOBALS['Language']->getText('plugin_tracker_permissions','plugin_tracker_full_access');
320
                break;
321
            case Tracker::PERMISSION_ADMIN:
322
                $params['name'] = $GLOBALS['Language']->getText('plugin_tracker_permissions','plugin_tracker_admin');
323
                break;
324
            case 'PLUGIN_TRACKER_ARTIFACT_ACCESS':
325
                $params['name'] = $GLOBALS['Language']->getText('plugin_tracker_permissions','plugin_tracker_artifact_access');
326
                break;
327
            case 'PLUGIN_TRACKER_WORKFLOW_TRANSITION':
328
                $params['name'] = $GLOBALS['Language']->getText('workflow_admin','permissions_transition');
329
                break;
330
            default:
331
                break;
332
            }
333
        }
334
    }
335
336
    function permission_get_object_type($params) {
337
        $type = $this->getObjectTypeFromPermissions($params);
338
        if ($type != false) {
0 ignored issues
show
It seems like you are loosely comparing $type of type string|false against false; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
339
            $params['object_type'] = $type;
340
        }
341
    }
342
343
    function getObjectTypeFromPermissions($params) {
344
        switch($params['permission_type']) {
345
            case 'PLUGIN_TRACKER_FIELD_SUBMIT':
346
            case 'PLUGIN_TRACKER_FIELD_READ':
347
            case 'PLUGIN_TRACKER_FIELD_UPDATE':
348
                return 'field';
349
            case Tracker::PERMISSION_SUBMITTER_ONLY:
350
            case Tracker::PERMISSION_SUBMITTER:
351
            case Tracker::PERMISSION_ASSIGNEE:
352
            case Tracker::PERMISSION_FULL:
353
            case Tracker::PERMISSION_ADMIN:
354
                return 'tracker';
355
            case 'PLUGIN_TRACKER_ARTIFACT_ACCESS':
356
                return 'artifact';
357
            case 'PLUGIN_TRACKER_WORKFLOW_TRANSITION':
358
                return 'workflow transition';
359
        }
360
        return false;
361
    }
362
363
    function permission_get_object_name($params) {
364
        if (!$params['object_name']) {
365
            $type = $this->getObjectTypeFromPermissions($params);
366
            if (in_array($params['permission_type'], array(Tracker::PERMISSION_ADMIN, Tracker::PERMISSION_FULL, Tracker::PERMISSION_SUBMITTER, Tracker::PERMISSION_ASSIGNEE, Tracker::PERMISSION_SUBMITTER_ONLY, 'PLUGIN_TRACKER_FIELD_SUBMIT', 'PLUGIN_TRACKER_FIELD_READ', 'PLUGIN_TRACKER_FIELD_UPDATE', 'PLUGIN_TRACKER_ARTIFACT_ACCESS'))) {
367
                $object_id = $params['object_id'];
368
                if ($type == 'tracker') {
369
                    $ret = (string)$object_id;
370
                    if ($tracker = TrackerFactory::instance()->getTrackerById($object_id)) {
371
                        $params['object_name'] = $tracker->getName();
372
                    }
373
                } else if ($type == 'field') {
374
                    $ret = (string)$object_id;
375
                    if ($field = Tracker_FormElementFactory::instance()->getFormElementById($object_id)) {
376
                        $ret = $field->getLabel() .' ('. $field->getTracker()->getName() .')';
377
                    }
378
                    $params['object_name'] =  $ret;
379
                } else if ($type == 'artifact') {
380
                    $ret = (string)$object_id;
381
                    if ($a  = Tracker_ArtifactFactory::instance()->getArtifactById($object_id)) {
382
                        $ret = 'art #'. $a->getId();
383
                        $semantics = $a->getTracker()
384
                                       ->getTrackerSemanticManager()
385
                                       ->getSemantics();
386
                        if (isset($semantics['title'])) {
387
                            if ($field = Tracker_FormElementFactory::instance()->getFormElementById($semantics['title']->getFieldId())) {
388
                                $ret .= ' - '. $a->getValue($field)->getText();
389
                            }
390
                        }
391
                    }
392
                    $params['object_name'] =  $ret;
393
                }
394
            }
395
        }
396
    }
397
398
    function permission_get_object_fullname($params) {
399
        $this->permission_get_object_name($params);
400
    }
401
402
    function permissions_for_ugroup($params) {
403
        if (!$params['results']) {
404
405
            $group_id = $params['group_id'];
406
            $hp = Codendi_HTMLPurifier::instance();
407
            $atid = $params['object_id'];
408
            $objname = $params['objname'];
409
410
            if (in_array($params['permission_type'], array(Tracker::PERMISSION_ADMIN, Tracker::PERMISSION_FULL, Tracker::PERMISSION_SUBMITTER, Tracker::PERMISSION_ASSIGNEE, Tracker::PERMISSION_SUBMITTER_ONLY, 'PLUGIN_TRACKER_FIELD_SUBMIT', 'PLUGIN_TRACKER_FIELD_READ', 'PLUGIN_TRACKER_FIELD_UPDATE', 'PLUGIN_TRACKER_ARTIFACT_ACCESS', 'PLUGIN_TRACKER_WORKFLOW_TRANSITION'))) {
411
                if (strpos($params['permission_type'], 'PLUGIN_TRACKER_ACCESS') === 0 || $params['permission_type'] === Tracker::PERMISSION_ADMIN) {
412
                    $params['results'] = $GLOBALS['Language']->getText('project_admin_editugroup','tracker')
413
                    .' <a href="'.TRACKER_BASE_URL.'/?tracker='.$atid.'&func=admin-perms-tracker">'
414
                    .$objname.'</a>';
415
416
                } else if (strpos($params['permission_type'], 'PLUGIN_TRACKER_FIELD') === 0) {
417
                    $field = Tracker_FormElementFactory::instance()->getFormElementById($atid);
418
                    $tracker_id = $field->getTrackerId();
419
420
                    $params['results'] = $GLOBALS['Language']->getText('project_admin_editugroup','tracker')
421
                    .' <a href="'.TRACKER_BASE_URL.'/?tracker='.$tracker_id.'&func=admin-perms-fields">'
422
                    .$objname.'</a>';
423
424
                } else if ($params['permission_type'] == 'PLUGIN_TRACKER_ARTIFACT_ACCESS') {
425
                    $params['results'] = $hp->purify($objname, CODENDI_PURIFIER_BASIC);
426
427
                } else if ($params['permission_type'] == 'PLUGIN_TRACKER_WORKFLOW_TRANSITION') {
428
                    $transition = TransitionFactory::instance()->getTransition($atid);
429
                    $tracker_id = $transition->getWorkflow()->getTrackerId();
430
                    $edit_transition = $transition->getFieldValueFrom().'_'.$transition->getFieldValueTo();
431
                    $params['results'] = '<a href="'.TRACKER_BASE_URL.'/?'. http_build_query(
432
                        array(
433
                            'tracker'         => $tracker_id,
434
                            'func'            => Workflow::FUNC_ADMIN_TRANSITIONS,
435
                            'edit_transition' => $edit_transition
436
                        )
437
                    ).'">'.$objname.'</a>';
438
                }
439
            }
440
        }
441
    }
442
443
    var $_cached_permission_user_allowed_to_change;
444
    function permission_user_allowed_to_change($params) {
445
        if (!$params['allowed']) {
446
            $allowed = array(
447
                Tracker::PERMISSION_ADMIN,
448
                Tracker::PERMISSION_FULL,
449
                Tracker::PERMISSION_SUBMITTER,
450
                Tracker::PERMISSION_SUBMITTER_ONLY,
451
                Tracker::PERMISSION_ASSIGNEE,
452
                'PLUGIN_TRACKER_FIELD_SUBMIT',
453
                'PLUGIN_TRACKER_FIELD_READ',
454
                'PLUGIN_TRACKER_FIELD_UPDATE',
455
                'PLUGIN_TRACKER_ARTIFACT_ACCESS',
456
                'PLUGIN_TRACKER_WORKFLOW_TRANSITION',
457
            );
458
            if (in_array($params['permission_type'], $allowed)) {
459
                $group_id  = $params['group_id'];
460
                $object_id = $params['object_id'];
461
                $type      = $this->getObjectTypeFromPermissions($params);
462
                if (!isset($this->_cached_permission_user_allowed_to_change[$type][$object_id])) {
463
                    switch ($type) {
464
                        case 'tracker':
465
                            if ($tracker = TrackerFactory::instance()->getTrackerById($object_id)) {
466
                                $this->_cached_permission_user_allowed_to_change[$type][$object_id] = $tracker->userIsAdmin();
467
                            }
468
                            break;
469
                        case 'field':
470
                            if ($field = Tracker_FormElementFactory::instance()->getFormElementById($object_id)) {
471
                                $this->_cached_permission_user_allowed_to_change[$type][$object_id] = $field->getTracker()->userIsAdmin();
472
                            }
473
                            break;
474
                        case 'artifact':
475
                            if ($a  = Tracker_ArtifactFactory::instance()->getArtifactById($object_id)) {
476
                                //TODO: manage permissions related to field "permission on artifact"
477
                                $this->_cached_permission_user_allowed_to_change[$type][$object_id] = $a->getTracker()->userIsAdmin();
478
                            }
479
                        case 'workflow transition':
480
                            if ($transition = TransitionFactory::instance()->getTransition($object_id)) {
481
                                $this->_cached_permission_user_allowed_to_change[$type][$object_id] = $transition->getWorkflow()->getTracker()->userIsAdmin();
482
                            }
483
                            break;
484
                    }
485
                }
486
                if (isset($this->_cached_permission_user_allowed_to_change[$type][$object_id])) {
487
                    $params['allowed'] = $this->_cached_permission_user_allowed_to_change[$type][$object_id];
488
                }
489
            }
490
        }
491
    }
492
493
    public function get_available_reference_natures($params) {
494
        $natures = array(Tracker_Artifact::REFERENCE_NATURE => array('keyword' => 'artifact',
495
                                                                     'label'   => 'Artifact Tracker v5'));
496
        $params['natures'] = array_merge($params['natures'], $natures);
497
    }
498
499
    public function get_artifact_reference_group_id($params) {
500
        $artifact = Tracker_ArtifactFactory::instance()->getArtifactByid($params['artifact_id']);
501
        if ($artifact) {
502
            $tracker = $artifact->getTracker();
503
            $params['group_id'] = $tracker->getGroupId();
504
        }
505
    }
506
507
    public function build_reference($params) {
508
        $row           = $params['row'];
509
        $params['ref'] = new Reference(
510
            $params['ref_id'],
511
            $row['keyword'],
512
            $row['description'],
513
            $row['link'],
514
            $row['scope'],
515
            $this->getServiceShortname(),
516
            Tracker_Artifact::REFERENCE_NATURE,
517
            $row['is_active'],
518
            $row['group_id']
519
        );
520
    }
521
522
    public function ajax_reference_tooltip($params) {
523
        if ($params['reference']->getServiceShortName() == $this->getServiceShortname()) {
524
            if ($params['reference']->getNature() == Tracker_Artifact::REFERENCE_NATURE) {
525
                $user = UserManager::instance()->getCurrentUser();
526
                $aid = $params['val'];
527
                if ($artifact = Tracker_ArtifactFactory::instance()->getArtifactByid($aid)) {
528
                    if ($artifact && $artifact->getTracker()->isActive()) {
529
                        echo $artifact->fetchTooltip($user);
530
                    } else {
531
                        echo $GLOBALS['Language']->getText('plugin_tracker_common_type', 'artifact_not_exist');
532
                    }
533
                }
534
            }
535
        }
536
    }
537
538
    public function url_verification_instance($params) {
539
        if (strpos($_SERVER['REQUEST_URI'], $this->getPluginPath()) === 0) {
540
            include_once 'Tracker/Tracker_URLVerification.class.php';
541
            $params['url_verification'] = new Tracker_URLVerification();
542
        }
543
    }
544
545
    /**
546
     * Hook: event raised when widget are instanciated
547
     *
548
     * @param Array $params
549
     */
550
    public function widget_instance($params) {
551
        switch ($params['widget']) {
552
            case Tracker_Widget_MyArtifacts::ID:
553
                $params['instance'] = new Tracker_Widget_MyArtifacts();
554
                break;
555
            case Tracker_Widget_MyRenderer::ID:
556
                $params['instance'] = new Tracker_Widget_MyRenderer();
557
                break;
558
            case Tracker_Widget_ProjectRenderer::ID:
559
                $params['instance'] = new Tracker_Widget_ProjectRenderer();
560
                break;
561
        }
562
    }
563
564
    public function service_icon($params) {
565
        $params['list_of_icon_unicodes'][$this->getServiceShortname()] = '\e80d';
566
    }
567
568
    /**
569
     * Hook: event raised when user lists all available widget
570
     *
571
     * @param Array $params
572
     */
573
    public function widgets($params) {
574
        switch ($params['owner_type']) {
575
            case WidgetLayoutManager::OWNER_TYPE_USER:
576
                $params['codendi_widgets'][] = Tracker_Widget_MyArtifacts::ID;
577
                $params['codendi_widgets'][] = Tracker_Widget_MyRenderer::ID;
578
                break;
579
580
            case WidgetLayoutManager::OWNER_TYPE_GROUP:
581
                $params['codendi_widgets'][] = Tracker_Widget_ProjectRenderer::ID;
582
                break;
583
        }
584
    }
585
586
    public function default_widgets_for_new_owner($params) {
587
        switch ($params['owner_type']) {
588
            case WidgetLayoutManager::OWNER_TYPE_USER:
589
                $params['widgets'][] = array(
590
                    'name'   => Tracker_Widget_MyArtifacts::ID,
591
                    'column' => '2',
592
                    'rank'   => '5',
593
                );
594
                break;
595
        }
596
    }
597
598
    /**
599
     * @see Event::REST_PROJECT_RESOURCES
600
     */
601
    public function rest_project_resources(array $params) {
602
        $injector = new Tracker_REST_ResourcesInjector();
603
        $injector->declareProjectPlanningResource($params['resources'], $params['project']);
604
    }
605
606
    function service_public_areas($params) {
607
        if ($params['project']->usesService($this->getServiceShortname())) {
608
            $tf = TrackerFactory::instance();
609
610
            // Get the artfact type list
611
            $trackers = $tf->getTrackersByGroupId($params['project']->getGroupId());
612
613
            if ($trackers) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $trackers of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
614
                $entries  = array();
615
                $purifier = Codendi_HTMLPurifier::instance();
616
                foreach($trackers as $t) {
617
                    if ($t->userCanView()) {
618
                        $name      = $purifier->purify($t->name, CODENDI_PURIFIER_CONVERT_HTML);
619
                        $entries[] = '<a href="'. TRACKER_BASE_URL .'/?tracker='. $t->id .'">'. $name .'</a>';
620
                    }
621
                }
622
                if ($entries) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $entries of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
623
                    $area = '';
624
                    $area .= '<a href="'. TRACKER_BASE_URL .'/?group_id='. $params['project']->getGroupId() .'">';
625
                    $area .= $GLOBALS['HTML']->getImage('ic/clipboard-list.png');
626
                    $area .= ' '. $GLOBALS['Language']->getText('plugin_tracker', 'service_lbl_key');
627
                    $area .= '</a>';
628
629
                    $area .= '<ul><li>'. implode('</li><li>', $entries) .'</li></ul>';
630
                    $params['areas'][] = $area;
631
                }
632
            }
633
        }
634
    }
635
636
    /**
637
     * When a project is deleted, we delete all its trackers
638
     *
639
     * @param mixed $params ($param['group_id'] the ID of the deleted project)
640
     *
641
     * @return void
642
     */
643
    function project_is_deleted($params) {
644
        $groupId = $params['group_id'];
645
        if ($groupId) {
646
            include_once 'Tracker/TrackerManager.class.php';
647
            $trackerManager = new TrackerManager();
648
            $trackerManager->deleteProjectTrackers($groupId);
649
        }
650
    }
651
652
   /**
653
     * Process the nightly job to send reminder on artifact correponding to given criteria
654
     *
655
     * @param Array $params Hook params
656
     *
657
     * @return Void
658
     */
659
    public function codendi_daily_start($params) {
660
        include_once 'Tracker/TrackerManager.class.php';
661
        $trackerManager = new TrackerManager();
662
        $logger = new BackendLogger();
663
        $logger->debug("[TDR] Tuleap daily start event: launch date reminder");
664
        return $trackerManager->sendDateReminder();
665
    }
666
667
    /**
668
     * Fill the list of subEvents related to tracker in the project history interface
669
     *
670
     * @param Array $params Hook params
671
     *
672
     * @return Void
673
     */
674
    public function fillProjectHistorySubEvents($params) {
675
        array_push($params['subEvents']['event_others'], 'tracker_date_reminder_add',
676
                                                         'tracker_date_reminder_edit',
677
                                                         'tracker_date_reminder_delete',
678
                                                         'tracker_date_reminder_sent'
679
        );
680
    }
681
682
    public function soap_description($params) {
683
        $params['end_points'][] = array(
684
            'title'       => 'Tracker',
685
            'wsdl'        => $this->getPluginPath().'/soap/?wsdl',
686
            'wsdl_viewer' => $this->getPluginPath().'/soap/view-wsdl',
687
            'changelog'   => $this->getPluginPath().'/soap/ChangeLog',
688
            'version'     => file_get_contents(dirname(__FILE__).'/../www/soap/VERSION'),
689
            'description' => 'Query and modify Trackers.',
690
        );
691
    }
692
693
    /**
694
     * @param array $params
695
     */
696
    public function agiledashboard_export_xml($params) {
697
        $can_bypass_threshold = true;
698
        $user_xml_exporter    = new UserXMLExporter(
699
            $this->getUserManager(),
700
            new UserXMLExportedCollection(new XML_RNGValidator(), new XML_SimpleXMLCDATAFactory())
701
        );
702
703
        $this->getTrackerXmlExport($user_xml_exporter, $can_bypass_threshold)
704
            ->exportToXml($params['project']->getID(), $params['into_xml']);
705
    }
706
707
    /**
708
     * @return TrackerXmlExport
709
     */
710
    private function getTrackerXmlExport(UserXMLExporter $user_xml_exporter, $can_bypass_threshold) {
711
        $rng_validator = new XML_RNGValidator();
712
713
        return new TrackerXmlExport(
714
            $this->getTrackerFactory(),
715
            $this->getTrackerFactory()->getTriggerRulesManager(),
716
            $rng_validator,
717
            new Tracker_Artifact_XMLExport(
718
                $rng_validator,
719
                $this->getArtifactFactory(),
720
                $can_bypass_threshold,
721
                $user_xml_exporter
722
            ),
723
            $user_xml_exporter
724
        );
725
    }
726
727
    /**
728
     *
729
     * @param array $params
730
     * @see Event::IMPORT_XML_PROJECT
731
     */
732
    public function import_xml_project($params) {
733
        TrackerXmlImport::build($params['user_finder'])->import(
734
            $params['project']->getId(),
735
            $params['xml_content'],
736
            $params['extraction_path']
737
        );
738
    }
739
740
    public function user_manager_get_user_instance(array $params) {
741
        if ($params['row']['user_id'] == Tracker_Workflow_WorkflowUser::ID) {
742
            $params['user'] = new Tracker_Workflow_WorkflowUser($params['row']);
743
        }
744
    }
745
    public function plugin_statistics_service_usage($params) {
746
747
        $dao             = new Tracker_ArtifactDao();
748
749
        $start_date      = strtotime($params['start_date']);
750
        $end_date        = strtotime($params['end_date']);
751
752
        $number_of_open_artifacts_between_two_dates   = $dao->searchSubmittedArtifactBetweenTwoDates($start_date, $end_date);
753
        $number_of_closed_artifacts_between_two_dates = $dao->searchClosedArtifactBetweenTwoDates($start_date, $end_date);
754
755
        $params['csv_exporter']->buildDatas($number_of_open_artifacts_between_two_dates, "Trackers v5 - Opened Artifacts");
756
        $params['csv_exporter']->buildDatas($number_of_closed_artifacts_between_two_dates, "Trackers v5 - Closed Artifacts");
757
    }
758
759
    /**
760
     * @see REST_RESOURCES
761
     */
762
    public function rest_resources($params) {
763
        $injector = new Tracker_REST_ResourcesInjector();
764
        $injector->populate($params['restler']);
765
    }
766
767
    /**
768
     * @see REST_GET_PROJECT_TRACKERS
769
     */
770
    public function rest_get_project_trackers($params) {
771
        $user              = UserManager::instance()->getCurrentUser();
772
        $planning_resource = $this->buildRightVersionOfProjectTrackersResource($params['version']);
773
        $project           = $params['project'];
774
775
        $this->checkProjectRESTAccess($project, $user);
776
777
        $params['result'] = $planning_resource->get(
778
            $user,
779
            $project,
780
            $params['limit'],
781
            $params['offset']
782
        );
783
    }
784
785
    /**
786
     * @see REST_OPTIONS_PROJECT_TRACKERS
787
     */
788
    public function rest_options_project_trackers($params) {
789
        $user             = UserManager::instance()->getCurrentUser();
790
        $project          = $params['project'];
791
        $tracker_resource = $this->buildRightVersionOfProjectTrackersResource($params['version']);
792
793
        $this->checkProjectRESTAccess($project, $user);
794
795
        $params['result'] = $tracker_resource->options(
796
            $user,
797
            $project,
798
            $params['limit'],
799
            $params['offset']
800
        );
801
    }
802
803
    private function checkProjectRESTAccess(Project $project, PFUser $user) {
804
        $project_authorization_class = '\\Tuleap\\REST\\ProjectAuthorization';
805
        $project_authorization       = new $project_authorization_class();
806
807
        $project_authorization->userCanAccessProject($user, $project, new Tracker_URLVerification());
808
    }
809
810
    private function buildRightVersionOfProjectTrackersResource($version) {
811
        $class_with_right_namespace = '\\Tuleap\\Tracker\\REST\\'.$version.'\\ProjectTrackersResource';
812
        return new $class_with_right_namespace;
813
    }
814
815
    public function agiledashboard_event_rest_get_milestone($params) {
816
        if ($this->buildRightVersionOfMilestonesBurndownResource($params['version'])->hasBurndown($params['user'], $params['milestone'])) {
817
            $params['milestone_representation']->enableBurndown();
818
        }
819
    }
820
821
    public function agiledashboard_event_rest_options_burndown($params) {
822
        $this->buildRightVersionOfMilestonesBurndownResource($params['version'])->options($params['user'], $params['milestone']);
823
    }
824
825
    public function agiledashboard_event_rest_get_burndown($params) {
826
        $params['burndown'] = $this->buildRightVersionOfMilestonesBurndownResource($params['version'])->get($params['user'], $params['milestone']);
827
    }
828
829
     private function buildRightVersionOfMilestonesBurndownResource($version) {
830
        $class_with_right_namespace = '\\Tuleap\\Tracker\\REST\\'.$version.'\\MilestonesBurndownResource';
831
        return new $class_with_right_namespace;
832
    }
833
834
    private function getTrackerSystemEventManager() {
835
        return new Tracker_SystemEventManager($this->getSystemEventManager());
836
    }
837
838
    private function getSystemEventManager() {
839
        return SystemEventManager::instance();
840
    }
841
842
    private function getMigrationManager() {
843
        return new Tracker_Migration_MigrationManager(
844
            $this->getTrackerSystemEventManager(),
845
            $this->getTrackerFactory(),
846
            $this->getArtifactFactory(),
847
            $this->getTrackerFormElementFactory(),
848
            $this->getUserManager(),
849
            $this->getProjectManager()
850
        );
851
    }
852
853
    private function getProjectManager() {
854
        return ProjectManager::instance();
855
    }
856
857
    private function getTrackerFactory() {
858
        return TrackerFactory::instance();
859
    }
860
861
    private function getUserManager() {
862
        return UserManager::instance();
863
    }
864
865
    private function getTrackerFormElementFactory() {
866
        return Tracker_FormElementFactory::instance();
867
    }
868
869
    private function getArtifactFactory() {
870
        return Tracker_ArtifactFactory::instance();
871
    }
872
873
    /**
874
     * @see Event::BACKEND_ALIAS_GET_ALIASES
875
     */
876
    public function backend_alias_get_aliases($params) {
877
        $config = new TrackerPluginConfig(
878
            new TrackerPluginConfigDao()
879
        );
880
881
        $src_dir  = ForgeConfig::get('codendi_dir');
882
        $script   = $src_dir .'/plugins/tracker/bin/emailgateway-wrapper.sh';
883
884
        $command = "sudo -u codendiadm $script";
885
886
        if ($config->isTokenBasedEmailgatewayEnabled() || $config->isInsecureEmailgatewayEnabled()) {
887
            $params['aliases'][] = new System_Alias(self::EMAILGATEWAY_TOKEN_ARTIFACT_UPDATE, "\"|$command\"");
888
        }
889
890
        if ($config->isInsecureEmailgatewayEnabled()) {
891
            $params['aliases'][] = new System_Alias(self::EMAILGATEWAY_INSECURE_ARTIFACT_CREATION, "\"|$command\"");
892
            $params['aliases'][] = new System_Alias(self::EMAILGATEWAY_INSECURE_ARTIFACT_UPDATE, "\"|$command\"");
893
        }
894
895
    }
896
    public function get_projectid_from_url($params) {
897
        $url = $params['url'];
898
        if (strpos($url,'/plugins/tracker/') === 0) {
899
            if (! $params['request']->get('tracker')) {
900
                return;
901
            }
902
903
            $tracker = TrackerFactory::instance()->getTrackerById($params['request']->get('tracker'));
904
            if ($tracker) {
905
                $params['project_id'] = $tracker->getGroupId();
906
            }
907
        }
908
    }
909
910
    /** @see Event::SYSTEM_EVENT_GET_CUSTOM_QUEUES */
911
    public function system_event_get_custom_queues(array $params) {
912
        $params['queues'][Tracker_SystemEvent_Tv3Tv5Queue::NAME] = new Tracker_SystemEvent_Tv3Tv5Queue();
913
    }
914
915
    /** @see Event::SYSTEM_EVENT_GET_TYPES_FOR_CUSTOM_QUEUE */
916
    public function system_event_get_types_for_custom_queue($params) {
917
        if ($params['queue'] === Tracker_SystemEvent_Tv3Tv5Queue::NAME) {
918
            $params['types'][] = SystemEvent_TRACKER_V3_MIGRATION::NAME;
919
        }
920
    }
921
922
    /** @see Event::SERVICES_TRUNCATED_EMAILS */
923
    public function services_truncated_emails(array $params) {
924
        $project = $params['project'];
925
        if ($project->usesService($this->getServiceShortname())) {
926
            $params['services'][] = $GLOBALS['Language']->getText('plugin_tracker', 'service_lbl_key');
927
        }
928
    }
929
930
    public function fulltextsearch_event_fetch_all_document_search_types($params) {
931
        $params['all_document_search_types'][] = array(
932
            'key'     => 'tracker',
933
            'name'    => $GLOBALS['Language']->getText('plugin_tracker', 'tracker_artifacts'),
934
            'info'    => $GLOBALS['Language']->getText('plugin_tracker', 'tracker_fulltextsearch_info'),
935
            'can_use' => false,
936
            'special' => true,
937
        );
938
    }
939
940
    public function fulltextsearch_event_fetch_project_tracker_fields($params) {
941
        $user     = $params['user'];
942
        $trackers = $this->getTrackerFactory()->getTrackersByGroupIdUserCanView($params['project_id'], $user);
943
        $fields   = $this->getTrackerFormElementFactory()->getUsedSearchableTrackerFieldsUserCanView($user, $trackers);
944
945
        $params['fields'] = $fields;
946
    }
947
948
    public function site_admin_configuration_tracker($params) {
949
        $label = $GLOBALS['Language']->getText('plugin_tracker', 'admin_tracker_template');
950
951
        $params['additional_entries'][] = '<li><a href="/plugins/tracker/?group_id=100">'. $label .'</a></li>';
952
    }
953
954
    public function fulltextsearch_event_does_tracker_service_use_ugroup($params) {
955
        $dao        = new Tracker_PermissionsDao();
956
        $ugroup_id  = $params['ugroup_id'];
957
        $project_id = $params['project_id'];
958
959
        if ($dao->isThereAnExplicitPermission($ugroup_id, $project_id)) {
960
            $params['is_used'] = true;
961
            return;
962
        }
963
964
        if ($dao->doAllItemsHaveExplicitPermissions($project_id)) {
965
            $params['is_used'] = false;
966
            return;
967
        }
968
969
        $params['is_used'] = $dao->isThereADefaultPermissionThatUsesUgroup($ugroup_id);
970
    }
971
972
    public function export_xml_project($params) {
973
        if (! isset($params['options']['tracker_id'])) {
974
            return;
975
        }
976
977
        $can_bypass_threshold = $params['options']['force'] === true;
978
        $tracker_id           = $params['options']['tracker_id'];
979
980
        $project    = $params['project'];
981
        $user       = $params['user'];
982
        $tracker    = $this->getTrackerFactory()->getTrackerById($tracker_id);
983
984
        if (! $tracker) {
985
            throw new Exception ('Tracker ID does not exist');
986
        }
987
988
        if ($tracker->getGroupId() != $project->getID()) {
989
            throw new Exception ('Tracker ID does not belong to project ID');
990
        }
991
992
        $this->getTrackerXmlExport($params['user_xml_exporter'], $can_bypass_threshold)
993
            ->exportSingleTrackerToXml($params['into_xml'], $tracker_id, $user, $params['archive']);
994
    }
995
996
    public function get_reference($params) {
997
        if ($this->isArtifactReferenceInMultipleTrackerServicesContext($params['keyword'])) {
998
            $artifact_id       = $params['value'];
999
            $keyword           = $params['keyword'];
1000
            $reference_manager = $params['reference_manager'];
1001
1002
            $tracker_reference_manager = $this->getTrackerReferenceManager($reference_manager);
1003
1004
            $reference = $tracker_reference_manager->getReference(
1005
                $keyword,
1006
                $artifact_id
1007
            );
1008
1009
            if ($reference) {
1010
                $params['reference'] = $reference;
1011
            }
1012
        }
1013
    }
1014
1015
    private function isArtifactReferenceInMultipleTrackerServicesContext($keyword) {
1016
        return (TrackerV3::instance()->available() && ($keyword === 'art' || $keyword === 'artifact'));
1017
    }
1018
1019
    /**
1020
     * @return Tracker_ReferenceManager
1021
     */
1022
    private function getTrackerReferenceManager(ReferenceManager $reference_manager) {
1023
        return new Tracker_ReferenceManager(
1024
            $reference_manager,
1025
            $this->getArtifactFactory()
1026
        );
1027
    }
1028
1029
    public function can_user_access_ugroup_info($params) {
1030
        $project = $params['project'];
1031
        $user    = $params['user'];
1032
1033
        $trackers = $this->getTrackerFactory()->getTrackersByGroupIdUserCanView($project->getID(), $user);
1034
        foreach ($trackers as $tracker) {
1035
            if ($tracker->hasFieldBindedToUserGroupsViewableByUser($user)) {
1036
                $params['can_access'] = true;
1037
                break;
1038
            }
1039
        }
1040
    }
1041
}
1042