Skip to content

Commit c1fb717

Browse files
committed
allow choosing glpi type when importing or merging mobile devices
1 parent 24f0ac1 commit c1fb717

File tree

6 files changed

+98
-42
lines changed

6 files changed

+98
-42
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## [UNRELEASED]
44

5+
### Added
6+
- Added support to choose importing/merging mobile devices as Computers or Phones
7+
58
### Fixes
69

710
- SQL error when merging the Jamf device linked to a GLPI asset

ajax/import.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,22 @@
5656
if (isset($_REQUEST['import_ids']) && is_array($_REQUEST['import_ids'])) {
5757
// Get data for each item to import
5858
$toimport = $DB->request([
59-
'SELECT' => ['type', 'jamf_type', 'jamf_items_id'],
60-
'FROM' => PluginJamfImport::getTable(),
61-
'WHERE' => [
62-
'id' => $_REQUEST['import_ids'],
63-
],
59+
'SELECT' => ['id', 'type', 'jamf_type', 'jamf_items_id'],
60+
'FROM' => PluginJamfImport::getTable(),
61+
'WHERE' => [
62+
'id' => $_REQUEST['import_ids']
63+
]
6464
]);
6565
// Trigger extension attribute definition sync
6666
PluginJamfMobileSync::syncExtensionAttributeDefinitions();
6767
PluginJamfComputerSync::syncExtensionAttributeDefinitions();
6868
// Import the requested device(s)
6969
foreach ($toimport as $data) {
70+
$glpi_itemtype = $_REQUEST['itemtype_overrides'][$data['id']] ?? $data['type'];
7071
if ($data['jamf_type'] === 'MobileDevice') {
71-
PluginJamfMobileSync::import($data['type'], $data['jamf_items_id']);
72+
PluginJamfMobileSync::import($glpi_itemtype, $data['jamf_items_id']);
7273
} else {
73-
PluginJamfComputerSync::import($data['type'], $data['jamf_items_id']);
74+
PluginJamfComputerSync::import($glpi_itemtype, $data['jamf_items_id']);
7475
}
7576
}
7677
} else {

ajax/merge.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@
5454
// Trigger extension attribute definition sync
5555
PluginJamfMobileSync::syncExtensionAttributeDefinitions();
5656
PluginJamfComputerSync::syncExtensionAttributeDefinitions();
57+
$supported_glpi_types = [
58+
'Computer' => PluginJamfComputerSync::getSupportedGlpiItemtypes(),
59+
'MobileDevice' => PluginJamfMobileSync::getSupportedGlpiItemtypes()
60+
];
5761
// An array of item IDs is required
5862
if (isset($_REQUEST['item_ids']) && is_array($_REQUEST['item_ids'])) {
5963
$failures = 0;
@@ -65,7 +69,7 @@
6569
$jamf_id = $data['jamf_id'];
6670
$itemtype = $data['itemtype'];
6771

68-
if (($itemtype !== 'Computer') && ($itemtype !== 'Phone')) {
72+
if (!in_array($itemtype, $supported_glpi_types[$data['jamf_type']])) {
6973
// Invalid itemtype for a mobile device
7074
throw new RuntimeException('Invalid itemtype!');
7175
}

front/merge.php

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -64,35 +64,46 @@
6464
$linked[$data['itemtype']][] = $data;
6565
}
6666

67+
$supported_glpi_types = [
68+
'Computer' => PluginJamfComputerSync::getSupportedGlpiItemtypes(),
69+
'MobileDevice' => PluginJamfMobileSync::getSupportedGlpiItemtypes()
70+
];
71+
6772
foreach ($pending as &$data) {
68-
$itemtype = $data['type'];
69-
/** @var CommonDBTM $item */
70-
$item = new $itemtype();
71-
$jamftype = ('PluginJamf' . $data['jamf_type']);
72-
$guesses = $DB->request([
73-
'SELECT' => ['id'],
74-
'FROM' => $itemtype::getTable(),
75-
'WHERE' => [
76-
'OR' => [
77-
'uuid' => $data['udid'],
78-
'name' => Sanitizer::sanitize($data['name']),
73+
$queries = [];
74+
foreach ($supported_glpi_types[$data['jamf_type']] as $type) {
75+
$queries[] = [
76+
'SELECT' => [
77+
new QueryExpression($DB::quoteValue($type) . ' AS ' . $DB::quoteName('itemtype')),
78+
'id'
79+
],
80+
'FROM' => $type::getTable(),
81+
'WHERE' => [
82+
'OR' => [
83+
'uuid' => $data['udid'],
84+
'name' => Sanitizer::sanitize($data['name'])
85+
],
86+
'is_deleted' => 0,
87+
'is_template' => 0
7988
],
80-
'is_deleted' => 0,
81-
'is_template' => 0,
82-
],
83-
'ORDER' => new QueryExpression("CASE WHEN uuid='" . $data['udid'] . "' THEN 0 ELSE 1 END"),
84-
'LIMIT' => 1,
85-
]);
86-
if (count($guesses)) {
87-
$data['guessed_item'] = $guesses->current()['id'];
88-
} else {
89-
$data['guessed_item'] = 0;
89+
'ORDER' => new QueryExpression("CASE WHEN uuid='" . $data['udid'] . "' THEN 0 ELSE 1 END"),
90+
'LIMIT' => 1
91+
];
92+
}
93+
$guesses = $DB->request(new QueryUnion($queries));
94+
$data['guessed_item'] = null;
95+
foreach ($guesses as $guess) {
96+
$data['guessed_item'][$guess['itemtype']] = $guess['id'];
9097
}
9198
}
9299

93100
TemplateRenderer::getInstance()->display('@jamf/merge.html.twig', [
94101
'pending' => $pending,
95102
'total_count' => $importcount,
96-
'linked' => $linked,
103+
'linked' => $linked,
104+
'supported_glpi_types' => array_map(
105+
static fn ($ts) => array_combine($ts, array_map(static fn ($t) => $t::getTypeName(1), $ts)),
106+
$supported_glpi_types
107+
)
97108
]);
98109
Html::footer();

templates/import.html.twig

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
* -------------------------------------------------------------------------
2929
*/
3030
#}
31+
{% import 'components/form/fields_macros.html.twig' as fields %}
3132

3233
<form>
3334
{{ include('components/pager.html.twig', {
@@ -57,14 +58,26 @@
5758
{% set import_checkbox %}
5859
<input type="checkbox" name="import_{{ data.id }}" class="form-check-input massive_action_checkbox">
5960
{% endset %}
60-
<tr>
61+
<tr data-import-id="{{ data.id }}">
6162
<td>{{ import_checkbox }}</td>
6263
<td>{{ data.jamf_items_id }}</td>
6364
<td>{{ data.jamf_type }}</td>
6465
<td>
6566
<a href="{{ call('PluginJamf' ~ data.jamf_type ~ '::getJamfDeviceURL', [data.jamf_items_id]) }}">{{ data.name }}</a>
6667
</td>
67-
<td>{{ data.type }}</td>
68+
{% if data.jamf_type == 'MobileDevice' %}
69+
<td>
70+
{{ fields.dropdownArrayField('glpi_type', data.type, {
71+
'Phone': 'Phone'|itemtype_name,
72+
'Computer': 'Computer'|itemtype_name,
73+
}, null, {
74+
no_label: true,
75+
full_width: true,
76+
}) }}
77+
</td>
78+
{% else %}
79+
<td>{{ data.type|itemtype_name }}</td>
80+
{% endif %}
6881
<td class="{{ data.udid is empty ? 'font-italic' : '' }}">
6982
{{ data.udid is not empty ? data.udid : _x('message', 'Not collected during discovery', 'jamf') }}
7083
</td>
@@ -90,12 +103,19 @@
90103
const import_ids = $(':checkbox:checked').filter(':not([name^="_checkall"])').map(function() {
91104
return this.name.replace("import","").substring(1).split('_');
92105
}).toArray();
106+
const itemtype_overrides = {};
107+
$('select[name="glpi_type"]').each((i, e) => {
108+
const itemtype = $(e).val();
109+
const id = $(e).closest('tr').attr('data-import-id');
110+
itemtype_overrides[id] = itemtype;
111+
});
93112
$.ajax({
94113
type: "POST",
95114
url: "{{ get_plugin_web_dir('jamf') }}/ajax/import.php",
96115
data: {
97116
action: "import",
98-
import_ids: import_ids
117+
import_ids: import_ids,
118+
itemtype_overrides: itemtype_overrides
99119
},
100120
contentType: 'application/json',
101121
beforeSend: () => {

templates/merge.html.twig

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,31 @@
5858
<td>
5959
<a href="{{ call('PluginJamf' ~ data.jamf_type ~ '::getJamfDeviceURL', [data.jamf_items_id]) }}">{{ data.name }}</a>
6060
</td>
61-
<td>{{ data.type }}</td>
61+
<td>
62+
{% if supported_glpi_types[data.jamf_type]|length > 0 %}
63+
{{ fields.dropdownArrayField('glpi_type', data.type, supported_glpi_types[data.jamf_type], null, {
64+
no_label: true,
65+
full_width: true,
66+
}) }}
67+
{% else %}
68+
{{ data.type|itemtype_name }}
69+
{% endif %}
70+
</td>
6271
<td>{{ data.jamf_type }}</td>
6372
<td class="{{ data.udid is empty ? 'font-italic' : '' }}">
6473
{{ data.udid is not empty ? data.udid : _x('message', 'Not collected during discovery', 'jamf') }}
6574
</td>
6675
<td>{{ data.date_discover|formatted_datetime }}</td>
6776
<td>
68-
{{ fields.dropdownField(data.type, 'items_id', data.guessed_item, null, {
69-
no_label: true,
70-
full_width: true,
71-
used: linked[data.type]|default([])|column('items_id')
72-
}) }}
77+
{% for glpi_type in supported_glpi_types[data.jamf_type] %}
78+
<span class="{{ glpi_type != data.type ? 'd-none' : '' }}" data-itemtype="{{ glpi_type }}">
79+
{{ fields.dropdownField(glpi_type, 'items_id', data.guessed_item[glpi_type], null, {
80+
no_label: true,
81+
full_width: true,
82+
used: linked[glpi_type]|default([])|column('items_id'),
83+
}) }}
84+
</span>
85+
{% endfor %}
7386
</td>
7487
</tr>
7588
{% endfor %}
@@ -93,12 +106,11 @@
93106
for (let i = 1; i < row_count; i++) {
94107
const row = table.rows[i];
95108
const jamf_id = row.cells[0].innerText;
96-
const itemtype = row.cells[2].innerText;
109+
const itemtype = $(row.cells[2]).find('select')[0].value;
97110
const jamf_type = row.cells[3].innerText;
98-
const glpi_sel = $(row.cells[6]).find('select')[0];
111+
const glpi_sel = $(row.cells[6]).find('span[data-itemtype]:not(.d-none) select')[0];
99112
const glpi_id = glpi_sel.value;
100113
if (glpi_id && glpi_id > 0) {
101-
data = [];
102114
post_data[glpi_id] = {'itemtype': itemtype, 'jamf_id': jamf_id, 'jamf_type': jamf_type};
103115
}
104116
}
@@ -115,6 +127,11 @@
115127
}
116128
});
117129
}
130+
$('select[name="glpi_type"]').on('change', (e) => {
131+
const selection = $(e.target).val();
132+
$(e.target).closest('tr').find('span[data-itemtype]').addClass('d-none');
133+
$(e.target).closest('tr').find('span[data-itemtype="' + selection + '"]').removeClass('d-none');
134+
});
118135
</script>
119136
</div>
120137
</form>

0 commit comments

Comments
 (0)