diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 29c3d44..7aca1bd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,7 +14,7 @@ jobs: run: | echo "tag_name=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - name: "Checkout" - uses: "actions/checkout@v3" + uses: "actions/checkout@v4" - name: "Build package" id: "build-package" uses: "glpi-project/tools/github-actions/build-package@0.6.4" diff --git a/hook.php b/hook.php index 4e64c64..534ece5 100644 --- a/hook.php +++ b/hook.php @@ -29,6 +29,9 @@ * ------------------------------------------------------------------------- */ +use Glpi\Api\HL\Controller\AbstractController; +use Glpi\Api\HL\Doc\Schema; + /** * Plugin install process * @@ -135,3 +138,155 @@ function plugin_credit_get_datas(NotificationTargetTicket $target) { ]; } } + +function plugin_credit_redefine_api_schemas(array $data): array { + // Handle modifications to existing schemas + foreach ($data['schemas'] as &$schema) { + if (!isset($schema['x-itemtype'])) { + continue; + } + if ($schema['x-itemtype'] === Entity::class) { + $schema['properties']['credits'] = [ + 'type' => Schema::TYPE_ARRAY, + 'items' => [ + 'type' => Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditEntity::class, + 'x-full-schema' => 'Credit', + 'x-join' => [ + 'table' => PluginCreditEntity::getTable(), + 'fkey' => 'id', + 'field' => 'entities_id', + 'primary-property' => 'id' + ], + 'properties' => [ + 'id' => [ + 'type' => Schema::TYPE_INTEGER, + 'format' => Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'name' => ['type' => Schema::TYPE_STRING], + 'is_recursive' => ['type' => Schema::TYPE_BOOLEAN], + 'is_active' => ['type' => Schema::TYPE_BOOLEAN], + 'type' => AbstractController::getDropdownTypeSchema(class: PluginCreditType::class, full_schema: 'PluginCreditType'), + 'date_begin' => [ + 'type' => Schema::TYPE_STRING, + 'format' => Schema::FORMAT_STRING_DATE, + 'x-field' => 'begin_date' + ], + 'date_end' => [ + 'type' => Schema::TYPE_STRING, + 'format' => Schema::FORMAT_STRING_DATE, + 'x-field' => 'end_date' + ], + 'quantity' => ['type' => Schema::TYPE_INTEGER], + 'over_consumption_allowed' => [ + 'type' => Schema::TYPE_BOOLEAN, + 'x-field' => 'overconsumption_allowed' + ], + ] + ] + ]; + $schema['properties']['credits_config'] = [ + 'type' => Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditEntityConfig::class, + 'x-full-schema' => 'CreditEntityConfig', + 'x-join' => [ + 'table' => PluginCreditEntityConfig::getTable(), + 'fkey' => 'id', + 'field' => 'entities_id', + 'primary-property' => 'id' + ], + 'properties' => [ + 'id' => [ + 'type' => Schema::TYPE_INTEGER, + 'format' => Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'consume_for_followups' => ['type' => Schema::TYPE_BOOLEAN, 'x-field' => 'consume_voucher_for_followups'], + 'consume_for_tasks' => ['type' => Schema::TYPE_BOOLEAN, 'x-field' => 'consume_voucher_for_tasks'], + 'consume_for_solutions' => ['type' => Schema::TYPE_BOOLEAN, 'x-field' => 'consume_voucher_for_solutions'], + 'followups_credit' => AbstractController::getDropdownTypeSchema( + class: PluginCreditEntity::class, + field: 'plugin_credit_entities_id_followups', + full_schema: 'Credit' + ), + 'tasks_credit' => AbstractController::getDropdownTypeSchema( + class: PluginCreditEntity::class, + field: 'plugin_credit_entities_id_tasks', + full_schema: 'Credit' + ), + 'solutions_credit' => AbstractController::getDropdownTypeSchema( + class: PluginCreditEntity::class, + field: 'plugin_credit_entities_id_solutions', + full_schema: 'Credit' + ), + ] + ]; + } else if ($schema['x-itemtype'] === Ticket::class) { + $schema['properties']['credits_consumed'] = [ + 'type' => Schema::TYPE_ARRAY, + 'items' => [ + 'type' => Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditTicket::class, + 'x-full-schema' => 'CreditConsumption', + 'x-join' => [ + 'table' => PluginCreditTicket::getTable(), + 'fkey' => 'id', + 'field' => 'tickets_id', + 'primary-property' => 'id' + ], + 'properties' => [ + 'id' => [ + 'type' => Schema::TYPE_INTEGER, + 'format' => Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'credit' => [ + 'type' => Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditTicket::class, + 'x-full-schema' => 'Credit', + 'properties' => [ + 'id' => [ + 'type' => Schema::TYPE_INTEGER, + 'format' => Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'name' => ['type' => Schema::TYPE_STRING], + ] + ], + 'date_creation' => [ + 'type' => Schema::TYPE_STRING, + 'format' => Schema::FORMAT_STRING_DATE_TIME, + 'x-readonly' => true, + ], + 'consumed' => ['type' => Schema::TYPE_INTEGER], + 'user' => AbstractController::getDropdownTypeSchema(class: User::class, full_schema: 'User'), + ] + ] + ]; + $schema['properties']['credits_config'] = [ + 'type' => Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditTicketConfig::class, + 'x-full-schema' => 'CreditTicketConfig', + 'x-join' => [ + 'table' => PluginCreditTicketConfig::getTable(), + 'fkey' => 'id', + 'field' => 'tickets_id', + 'primary-property' => 'id' + ], + 'properties' => [ + 'id' => [ + 'type' => Schema::TYPE_INTEGER, + 'format' => Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'followups_credit' => AbstractController::getDropdownTypeSchema(class: PluginCreditEntity::class, field: 'plugin_credit_entities_id_followups', full_schema: 'Credit'), + 'tasks_credit' => AbstractController::getDropdownTypeSchema(class: PluginCreditEntity::class, field: 'plugin_credit_entities_id_tasks', full_schema: 'Credit'), + 'solutions_credit' => AbstractController::getDropdownTypeSchema(class: PluginCreditEntity::class, field: 'plugin_credit_entities_id_solutions', full_schema: 'Credit'), + ] + ]; + } + } + + return $data; +} diff --git a/inc/apicontroller.class.php b/inc/apicontroller.class.php new file mode 100644 index 0000000..9db9de2 --- /dev/null +++ b/inc/apicontroller.class.php @@ -0,0 +1,182 @@ +. + * ------------------------------------------------------------------------- + * @author François Legastelois + * @copyright Copyright (C) 2017-2023 by Credit plugin team. + * @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html + * @link https://github.com/pluginsGLPI/credit + * ------------------------------------------------------------------------- + */ + +use Glpi\Api\HL\Controller\AbstractController; +use Glpi\Api\HL\Doc as Doc; +use Glpi\Api\HL\Route; +use Glpi\Http\Request; +use Glpi\Http\Response; + +#[Route(path: '/Credit', priority: 1, tags: ['Credit'])] +final class PluginCreditApicontroller extends AbstractController +{ + protected static function getRawKnownSchemas(): array + { + $schemas = []; + $schemas['Credit'] = [ + 'type' => Doc\Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditEntity::class, + 'properties' => [ + 'id' => [ + 'type' => Doc\Schema::TYPE_INTEGER, + 'format' => Doc\Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'name' => ['type' => Doc\Schema::TYPE_STRING], + 'entity' => AbstractController::getDropdownTypeSchema(class: Entity::class, full_schema: 'Entity'), + 'is_recursive' => ['type' => Doc\Schema::TYPE_BOOLEAN], + 'is_active' => ['type' => Doc\Schema::TYPE_BOOLEAN], + 'type' => AbstractController::getDropdownTypeSchema(class: PluginCreditType::class, full_schema: 'PluginCreditType'), + 'date_begin' => [ + 'type' => Doc\Schema::TYPE_STRING, + 'format' => Doc\Schema::FORMAT_STRING_DATE, + 'x-field' => 'begin_date' + ], + 'date_end' => [ + 'type' => Doc\Schema::TYPE_STRING, + 'format' => Doc\Schema::FORMAT_STRING_DATE, + 'x-field' => 'end_date' + ], + 'quantity' => ['type' => Doc\Schema::TYPE_INTEGER], + 'over_consumption_allowed' => [ + 'type' => Doc\Schema::TYPE_BOOLEAN, + 'x-field' => 'overconsumption_allowed' + ], + ] + ]; + $schemas['CreditType'] = [ + 'type' => Doc\Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditEntity::class, + 'properties' => [ + 'id' => [ + 'type' => Doc\Schema::TYPE_INTEGER, + 'format' => Doc\Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'name' => ['type' => Doc\Schema::TYPE_STRING], + 'comment' => ['type' => Doc\Schema::TYPE_STRING], + 'entity' => AbstractController::getDropdownTypeSchema(class: Entity::class, full_schema: 'Entity'), + 'is_recursive' => ['type' => Doc\Schema::TYPE_BOOLEAN], + 'parent' => AbstractController::getDropdownTypeSchema(class: PluginCreditType::class, full_schema: 'CreditType'), + 'level' => ['type' => Doc\Schema::TYPE_INTEGER], + 'date_creation' => [ + 'type' => Doc\Schema::TYPE_STRING, + 'format' => Doc\Schema::FORMAT_STRING_DATE_TIME, + 'x-readonly' => true, + ], + 'date_mod' => [ + 'type' => Doc\Schema::TYPE_STRING, + 'format' => Doc\Schema::FORMAT_STRING_DATE_TIME, + 'x-readonly' => true, + ], + ] + ]; + $schemas['CreditConsumption'] = [ + 'type' => Doc\Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditEntity::class, + 'properties' => [ + 'id' => [ + 'type' => Doc\Schema::TYPE_INTEGER, + 'format' => Doc\Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'ticket' => AbstractController::getDropdownTypeSchema(class: Ticket::class, full_schema: 'Ticket'), + 'credit' => [ + 'type' => Doc\Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditTicket::class, + 'x-full-schema' => 'Credit', + 'properties' => [ + 'id' => [ + 'type' => Doc\Schema::TYPE_INTEGER, + 'format' => Doc\Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'name' => ['type' => Doc\Schema::TYPE_STRING], + ] + ], + 'date_creation' => [ + 'type' => Doc\Schema::TYPE_STRING, + 'format' => Doc\Schema::FORMAT_STRING_DATE_TIME, + 'x-readonly' => true, + ], + 'consumed' => ['type' => Doc\Schema::TYPE_INTEGER], + 'user' => AbstractController::getDropdownTypeSchema(class: User::class, full_schema: 'User'), + ] + ]; + $schemas['CreditEntityConfig'] = [ + 'type' => Doc\Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditEntityConfig::class, + 'properties' => [ + 'id' => [ + 'type' => Doc\Schema::TYPE_INTEGER, + 'format' => Doc\Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'entity' => AbstractController::getDropdownTypeSchema(class: Entity::class, full_schema: 'Entity'), + 'consume_for_followups' => ['type' => Doc\Schema::TYPE_BOOLEAN, 'x-field' => 'consume_voucher_for_followups'], + 'consume_for_tasks' => ['type' => Doc\Schema::TYPE_BOOLEAN, 'x-field' => 'consume_voucher_for_tasks'], + 'consume_for_solutions' => ['type' => Doc\Schema::TYPE_BOOLEAN, 'x-field' => 'consume_voucher_for_solutions'], + 'followups_credit' => AbstractController::getDropdownTypeSchema( + class: PluginCreditEntity::class, + field: 'plugin_credit_entities_id_followups', + full_schema: 'Credit' + ), + 'tasks_credit' => AbstractController::getDropdownTypeSchema( + class: PluginCreditEntity::class, + field: 'plugin_credit_entities_id_tasks', + full_schema: 'Credit' + ), + 'solutions_credit' => AbstractController::getDropdownTypeSchema( + class: PluginCreditEntity::class, + field: 'plugin_credit_entities_id_solutions', + full_schema: 'Credit' + ), + ] + ]; + $schemas['CreditTicketConfig'] = [ + 'type' => Doc\Schema::TYPE_OBJECT, + 'x-itemtype' => PluginCreditTicketConfig::class, + 'properties' => [ + 'id' => [ + 'type' => Doc\Schema::TYPE_INTEGER, + 'format' => Doc\Schema::FORMAT_INTEGER_INT64, + 'x-readonly' => true, + ], + 'ticket' => AbstractController::getDropdownTypeSchema(class: Ticket::class, full_schema: 'Ticket'), + 'followups_credit' => AbstractController::getDropdownTypeSchema(class: PluginCreditEntity::class, full_schema: 'Credit'), + 'tasks_credit' => AbstractController::getDropdownTypeSchema(class: PluginCreditEntity::class, full_schema: 'Credit'), + 'solutions_credit' => AbstractController::getDropdownTypeSchema(class: PluginCreditEntity::class, full_schema: 'Credit'), + ] + ]; + return $schemas; + } +} + diff --git a/setup.php b/setup.php index df20c8a..da4a526 100644 --- a/setup.php +++ b/setup.php @@ -29,12 +29,14 @@ * ------------------------------------------------------------------------- */ +use Glpi\Plugin\Hooks; + define('PLUGIN_CREDIT_VERSION', '1.12.0'); // Minimal GLPI version, inclusive define("PLUGIN_CREDIT_MIN_GLPI", "10.0.0"); // Maximum GLPI version, exclusive -define("PLUGIN_CREDIT_MAX_GLPI", "10.0.99"); +define("PLUGIN_CREDIT_MAX_GLPI", "10.1.99"); /** * Init hooks of the plugin. @@ -49,39 +51,43 @@ function plugin_init_credit() { $PLUGIN_HOOKS['csrf_compliant']['credit'] = true; - if (Session::getLoginUserID() && $plugin->isActivated('credit')) { + if ($plugin->isActivated('credit')) { + $PLUGIN_HOOKS[Hooks::REDEFINE_API_SCHEMAS]['credit'] = 'plugin_credit_redefine_api_schemas'; + $PLUGIN_HOOKS[Hooks::API_CONTROLLERS]['credit'] = ['PluginCreditApicontroller']; + if (Session::getLoginUserID()) { - Plugin::registerClass( - 'PluginCreditEntity', - [ - 'notificationtemplates_types' => true, - 'addtabon' => 'Entity' - ] - ); + Plugin::registerClass( + 'PluginCreditEntity', + [ + 'notificationtemplates_types' => true, + 'addtabon' => 'Entity' + ] + ); - if (Session::haveRightsOr('ticket', [Ticket::STEAL, Ticket::OWN])) { - Plugin::registerClass('PluginCreditTicket', ['addtabon' => 'Ticket']); + if (Session::haveRightsOr('ticket', [Ticket::STEAL, Ticket::OWN])) { + Plugin::registerClass('PluginCreditTicket', ['addtabon' => 'Ticket']); - $PLUGIN_HOOKS['post_item_form']['credit'] = [ - 'PluginCreditTicket', - 'displayVoucherInTicketProcessingForm' - ]; + $PLUGIN_HOOKS['post_item_form']['credit'] = [ + 'PluginCreditTicket', + 'displayVoucherInTicketProcessingForm' + ]; - $PLUGIN_HOOKS['item_add']['credit'] = [ - 'ITILFollowup' => ['PluginCreditTicket', 'consumeVoucher'], - 'ITILSolution' => ['PluginCreditTicket', 'consumeVoucher'], - 'TicketTask' => ['PluginCreditTicket', 'consumeVoucher'], - 'Ticket' => ['PluginCreditTicketConfig', 'updateConfig'], - ]; - // Update config on 'pre_item_update' as only changing these fields in ticket form will not trigger 'item_update'. - $PLUGIN_HOOKS['pre_item_update']['credit'] = [ - 'Ticket' => ['PluginCreditTicketConfig', 'updateConfig'], - ]; - } - $PLUGIN_HOOKS['add_javascript']['credit'] = [ - 'js/credit.js' - ]; - $PLUGIN_HOOKS['item_get_datas']['credit'] = ['NotificationTargetTicket' => 'plugin_credit_get_datas']; + $PLUGIN_HOOKS['item_add']['credit'] = [ + 'ITILFollowup' => ['PluginCreditTicket', 'consumeVoucher'], + 'ITILSolution' => ['PluginCreditTicket', 'consumeVoucher'], + 'TicketTask' => ['PluginCreditTicket', 'consumeVoucher'], + 'Ticket' => ['PluginCreditTicketConfig', 'updateConfig'], + ]; + // Update config on 'pre_item_update' as only changing these fields in ticket form will not trigger 'item_update'. + $PLUGIN_HOOKS['pre_item_update']['credit'] = [ + 'Ticket' => ['PluginCreditTicketConfig', 'updateConfig'], + ]; + } + $PLUGIN_HOOKS['add_javascript']['credit'] = [ + 'js/credit.js' + ]; + $PLUGIN_HOOKS['item_get_datas']['credit'] = ['NotificationTargetTicket' => 'plugin_credit_get_datas']; + } } Plugin::registerClass(PluginCreditProfile::class, ['addtabon' => Profile::class]);