Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [unreleased]

### Added
- Add an `Orderable` capacity for GLPI 11 custom asset definitions.

### Fixed

- Fix generate associated item massive action
Expand Down
104 changes: 104 additions & 0 deletions inc/orderablecapacity.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

/**
* -------------------------------------------------------------------------
* Order plugin for GLPI
* -------------------------------------------------------------------------
*
* LICENSE
*
* This file is part of Order.
*
* Order is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Order is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Order. If not, see <http://www.gnu.org/licenses/>.
* -------------------------------------------------------------------------
* @copyright Copyright (C) 2009-2023 by Order plugin team.
* @license GPLv3 https://www.gnu.org/licenses/gpl-3.0.html
* @link https://github.com/pluginsGLPI/order
* -------------------------------------------------------------------------
*/

use Glpi\Asset\Capacity\AbstractCapacity;
use Glpi\Asset\CapacityConfig;

/**
* Capacity that flags a GLPI 11 custom asset definition as orderable
* through the Order plugin. When enabled on an asset definition (Setup ->
* Asset definitions -> {your asset} -> Capacities), the corresponding
* generated asset class is appended to $ORDER_TYPES and becomes selectable
* as an Item type when creating a Product reference.
*/
class PluginOrderOrderableCapacity extends AbstractCapacity
{
public function getLabel(): string
{
return __('Orderable', 'order');
}

public function getIcon(): string
{
return 'ti ti-shopping-cart';
}

public function getDescription(): string
{
return __(
'Allow this asset to be referenced as a Product reference and '
. 'generated from the Generate item massive action.',
'order',
);
}

public function getCapacityUsageDescription(string $classname): string
{
$count = 0;
if (class_exists('PluginOrderReference')) {
$count = countElementsInTable(
PluginOrderReference::getTable(),
['itemtype' => $classname],
);
}

return sprintf(
_n('Used by %d order reference', 'Used by %d order references', $count, 'order'),
$count,
);
}

/**
* Clean up plugin data linked to the asset class when the capacity is
* disabled on its definition: remove order line items first (parent
* Product references refuse deletion via pre_deleteItem() while still
* referenced by orders_items), then remove the references themselves.
* Free-form references are intentionally left untouched, as they are
* standalone records that do not reference any itemtype.
*/
public function onCapacityDisabled(string $classname, CapacityConfig $config): void
{
if (class_exists('PluginOrderOrder_Item')) {
(new PluginOrderOrder_Item())->deleteByCriteria(
['itemtype' => $classname],
force: true,
history: false,
);
}

if (class_exists('PluginOrderReference')) {
(new PluginOrderReference())->deleteByCriteria(
['itemtype' => $classname],
force: true,
history: false,
);
}
}
}
26 changes: 26 additions & 0 deletions setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
* -------------------------------------------------------------------------
*/

use Glpi\Asset\AssetDefinitionManager;

use function Safe\define;

define('PLUGIN_ORDER_VERSION', '2.12.6');
Expand Down Expand Up @@ -125,6 +127,30 @@ function plugin_init_order()
'Pdu',
];


// Register the Orderable capacity for GLPI 11 custom assets and append
// any custom asset class that has it enabled to $ORDER_TYPES, provided
// the current user is allowed to view it.
if (class_exists(AssetDefinitionManager::class)) {
$asset_manager = AssetDefinitionManager::getInstance();
$orderable_capacity = new PluginOrderOrderableCapacity();
$asset_manager->registerCapacity($orderable_capacity);
$asset_manager->bootDefinitions();
foreach ($asset_manager->getDefinitions(true) as $definition) {
if (!$definition->hasCapacityEnabled($orderable_capacity)) {
continue;
}

$custom_asset_class = $definition->getAssetClassName();
if (
!in_array($custom_asset_class, $ORDER_TYPES, true)
&& $custom_asset_class::canView()
) {
$ORDER_TYPES[] = $custom_asset_class;
}
}
}

Comment on lines +130 to +153
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good start =)

However, the Order plugin should introduce an "Order" capability for the custom Asset, allowing this feature to be enabled or disabled on a per-asset basis.

Additionally, this functionality should verify the read permissions of the currently authenticated user for the specified custom Asset before proceeding.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review @stonebuzz, both points were spot on.

The branch has been updated (force-pushed to keep a single clean commit, 6f94427). Summary of the changes:

1. New Orderable capacityinc/orderablecapacity.class.php introduces PluginOrderOrderableCapacity extending \Glpi\Asset\Capacity\AbstractCapacity. Admins now toggle it per asset definition under Setup → Asset definitions → {asset} → Capacities. Provides label, icon (ti ti-shopping-cart), description, and a usage count based on existing PluginOrderReference rows.

2. setup.php filtering — registers the capacity with AssetDefinitionManager, then iterates active definitions and appends a class to $ORDER_TYPES only when:

  • the Orderable capacity is enabled on that definition, and
  • $class::canView() passes for the current user (which delegates to the asset's AssignableItem READ check + the definition's is_active flag).

End-to-end re-tested on GLPI 11.0.6 / PHP 8.3:

Scenario Result
Capacity appears in the Capacities tab with proper label/icon/description
Capacity disabled → custom asset is absent from Item type dropdown
Capacity enabled → custom asset appears, references can be created
Generate item massive action renders and submits
Items reach Taken delivery state, generated assets visible in Assets section
Native itemtypes (Computer, Monitor, Printer, etc.) unaffected

Also updated the PR description (top of this thread) and the CHANGELOG entry to reflect the new opt-in design.

Let me know if you'd like any adjustments — happy to iterate.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You must declare your capacity in order for it to appear in the list.

This should be done in the setup.php file using:

AssetDefinitionManager::getInstance()->registerCapacity(...)

In addition, when a capacity is disabled, the associated data must be properly cleaned from the database.

In particular, this concerns the glpi_plugins_orderorder_item table, which—if I recall correctly—stores the relationship between an asset and an order.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the follow-up @stonebuzz, the new commit 5fd0975 addresses the data cleanup point.

On registerCapacity() — small clarification: the current branch (6f94427 and now 5fd0975) already declares the capacity through \Glpi\Asset\AssetDefinitionManager::getInstance()->registerCapacity(...) in setup.php, so it appears in the Capacities tab on GLPI 11 asset definitions and the Orderable toggle is admin-controlled. The inline review thread above is anchored to the original ea13dd1 push (the auto-register block) which is no longer in the branch — that may be why it reads as if the registration is missing.

On the cleanup — implemented onCapacityDisabled() on PluginOrderOrderableCapacity. When an admin disables Orderable on a definition, the callback removes:

  • order line items in glpi_plugin_order_orders_items whose itemtype matches the disabled custom asset class;
  • product references in glpi_plugin_order_references whose itemtype matches the disabled custom asset class.

The cascade order matters: PluginOrderReference::pre_deleteItem() rejects deletion while a reference is still in use by orders_items, so child records are deleted before parents. Free-form references (PluginOrderReferenceFree) are intentionally left untouched as they carry no itemtype reference.

End-to-end tested on GLPI 11.0.6 / PHP 8.3 on two installations:

Scenario Result
Disable capacity → references and orders_items for the targeted class are removed
Native itemtypes (Computer, Monitor, Printer, …) are untouched
Other custom assets that still have the capacity enabled are untouched
Re-enabling restores the asset class in the Item type dropdown; new references and order items can be created
The capacity description shows the live "Used by N order references" count, surfaced in the GLPI confirmation dialog before disabling

Specifically on the second installation, disabling the capacity on a small custom asset definition while keeping a much larger one (~12k order line items, ~600 references) enabled left the larger one fully intact — confirming the targeted, per-class scope of the cleanup.

Happy to iterate further if you'd like adjustments.

$CFG_GLPI['plugin_order_types'] = $ORDER_TYPES;

$PLUGIN_HOOKS['pre_item_purge']['order'] = [
Expand Down