- form das abas Redmine exibe/envia custom_field_values (Tipo de Projeto etc.) - createProjectFull normaliza o identificador (minúsculas) - sync da aba de projeto usa syncMetadata completo (não apaga mais o cache) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
158 lines
6.1 KiB
PHP
158 lines
6.1 KiB
PHP
<?php
|
|
|
|
if (!defined('GLPI_ROOT')) {
|
|
die("Sorry. You can't access this file directly");
|
|
}
|
|
|
|
class PluginRedmineProject extends CommonDBTM {
|
|
|
|
static function getTypeName($nb = 0) {
|
|
return 'Redmine';
|
|
}
|
|
|
|
function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) {
|
|
if ($item->getType() == 'Project') {
|
|
return self::createTabEntry(__('Redmine', 'redmine'), 0, $item::getType(), 'fas fa-sitemap');
|
|
}
|
|
return '';
|
|
}
|
|
|
|
static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) {
|
|
if ($item->getType() == 'Project') {
|
|
self::showForProject($item);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static function getIcon() {
|
|
return 'fas fa-sitemap';
|
|
}
|
|
|
|
static function showForProject(Project $project) {
|
|
global $DB, $CFG_GLPI;
|
|
|
|
$projects_id = $project->getID();
|
|
$form_url = $CFG_GLPI['root_doc'] . '/plugins/redmine/front/project.form.php';
|
|
|
|
// Build {id: name} of Redmine projects from cache IN PHP (Twig's merge
|
|
// renumbers integer keys, which corrupts the option values).
|
|
$project_options = self::getRedmineProjectOptions();
|
|
|
|
// Already linked?
|
|
$iterator = $DB->request([
|
|
'FROM' => 'glpi_plugin_redmine_projects',
|
|
'WHERE' => ['projects_id' => $projects_id]
|
|
]);
|
|
|
|
if (count($iterator) > 0) {
|
|
$link = $iterator->current();
|
|
$redmineProjectId = (int) $link['redmine_project_id'];
|
|
|
|
$cat_options = [];
|
|
foreach (PluginRedmineRedmineapi::getProjectCategories($redmineProjectId) as $c) {
|
|
if (isset($c['id'], $c['name'])) {
|
|
$cat_options[$c['id']] = $c['name'];
|
|
}
|
|
}
|
|
|
|
\Glpi\Application\View\TemplateRenderer::getInstance()->display('@redmine/project_linked.html.twig', [
|
|
'action_url' => $form_url,
|
|
'owner_field' => 'projects_id',
|
|
'owner_id' => $projects_id,
|
|
'redmine_project_id' => $redmineProjectId,
|
|
'redmine_project_name' => $project_options[$redmineProjectId] ?? '',
|
|
'cat_options' => $cat_options,
|
|
'default_category_id' => (int) ($link['default_category_id'] ?? 0),
|
|
'csrf_token_value' => Session::getNewCSRFToken(),
|
|
]);
|
|
return;
|
|
}
|
|
|
|
$description = \Glpi\RichText\RichText::getTextFromHtml($project->fields['content'], false, true, true);
|
|
|
|
\Glpi\Application\View\TemplateRenderer::getInstance()->display('@redmine/project_form.html.twig', [
|
|
'action_url' => $form_url,
|
|
'owner_field' => 'projects_id',
|
|
'owner_id' => $projects_id,
|
|
'project_options' => self::getRedmineProjectOptions(true),
|
|
'custom_fields' => self::getProjectCustomFieldDefs(),
|
|
'project_name' => $project->fields['name'],
|
|
'project_description' => $description,
|
|
'project_identifier' => 'glpi-proj-' . $projects_id,
|
|
'modules' => self::getModules(),
|
|
'csrf_token_value' => Session::getNewCSRFToken()
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* {id: name} map of the cached Redmine projects (PHP preserves integer keys).
|
|
* @return array
|
|
*/
|
|
static function getRedmineProjectOptions($activeOnly = false) {
|
|
global $DB;
|
|
$it = $DB->request(['FROM' => 'glpi_plugin_redmine_configs', 'WHERE' => ['id' => 1]]);
|
|
$config = count($it) > 0 ? $it->current() : [];
|
|
$metadata = !empty($config['metadata_cache']) ? json_decode($config['metadata_cache'], true) : [];
|
|
$opts = [];
|
|
foreach (($metadata['projects'] ?? []) as $rp) {
|
|
if (!isset($rp['id'], $rp['name'])) {
|
|
continue;
|
|
}
|
|
// status: 1=ativo, 5=fechado, 9=arquivado. Issues só podem ser
|
|
// criadas em projetos ativos, então o dropdown só mostra esses.
|
|
if ($activeOnly && isset($rp['status']) && (int) $rp['status'] !== 1) {
|
|
continue;
|
|
}
|
|
$opts[$rp['id']] = $rp['name'];
|
|
}
|
|
return $opts;
|
|
}
|
|
|
|
/**
|
|
* Project custom field definitions for the create form (from metadata cache).
|
|
* Some Redmine setups make these mandatory on project creation.
|
|
* @return array of ['id','name','field_format','is_required','options'=>{value: value}]
|
|
*/
|
|
static function getProjectCustomFieldDefs() {
|
|
global $DB;
|
|
$it = $DB->request(['FROM' => 'glpi_plugin_redmine_configs', 'WHERE' => ['id' => 1]]);
|
|
$config = count($it) > 0 ? $it->current() : [];
|
|
$metadata = !empty($config['metadata_cache']) ? json_decode($config['metadata_cache'], true) : [];
|
|
$defs = [];
|
|
foreach (($metadata['project_custom_fields'] ?? []) as $f) {
|
|
$options = [];
|
|
foreach (($f['possible_values'] ?? []) as $pv) {
|
|
if (isset($pv['value'])) {
|
|
$options[$pv['value']] = $pv['value'];
|
|
}
|
|
}
|
|
$defs[] = [
|
|
'id' => (int) $f['id'],
|
|
'name' => $f['name'],
|
|
'field_format' => $f['field_format'] ?? 'string',
|
|
'is_required' => (bool) ($f['is_required'] ?? false),
|
|
'options' => $options,
|
|
];
|
|
}
|
|
return $defs;
|
|
}
|
|
|
|
/**
|
|
* Redmine project modules offered on creation.
|
|
* @return array
|
|
*/
|
|
static function getModules() {
|
|
return [
|
|
'issue_tracking' => 'Gerenciamento de Tarefas',
|
|
'time_tracking' => 'Gerenciamento de tempo',
|
|
'news' => 'Notícias',
|
|
'documents' => 'Documentos',
|
|
'files' => 'Arquivos',
|
|
'wiki' => 'Wiki',
|
|
'repository' => 'Repositório',
|
|
'boards' => 'Fóruns',
|
|
'calendar' => 'Calendário',
|
|
'gantt' => 'Gantt'
|
|
];
|
|
}
|
|
}
|