setDefault(self::DEFAULT_VALUE) ->setSaveType(ZBX_WIDGET_FIELD_TYPE_STR) ->setValidationRules(['type' => API_OBJECTS, 'flags' => API_PRESERVE_KEYS, 'fields' => [ 'name' => ['type' => API_STRING_UTF8, 'flags' => API_REQUIRED | API_NOT_EMPTY, 'length' => 255], 'order' => ['type' => API_INT32, 'in' => '1:'.ZBX_MAX_INT32, 'default' => 1], 'parent' => ['type' => API_INT32, 'in' => '0:'.ZBX_MAX_INT32, 'default' => 0], 'sysmapid' => ['type' => API_ID, 'default' => '0'] ]]); } public function setValue($value): self { $this->value = (array) $value; return $this; } public function validate(bool $strict = false): array { $errors = parent::validate($strict); if (!$errors) { $this->setValue(self::validateNavTree($this->getValue(), $errors)); } return $errors; } public function toApi(array &$widget_fields = []): void { $value = $this->getValue(); foreach ($value as $index => $val) { $widget_fields[] = [ 'type' => $this->save_type, 'name' => $this->name.'.name.'.$index, 'value' => $val['name'] ]; // Add default values to avoid check of key existence. $val = array_merge([ 'order' => 1, 'parent' => 0, 'sysmapid' => 0 ], $val); if ($val['order'] != 1) { $widget_fields[] = [ 'type' => ZBX_WIDGET_FIELD_TYPE_INT32, 'name' => $this->name.'.order.'.$index, 'value' => $val['order'] ]; } if ($val['parent'] != 0) { $widget_fields[] = [ 'type' => ZBX_WIDGET_FIELD_TYPE_INT32, 'name' => $this->name.'.parent.'.$index, 'value' => $val['parent'] ]; } if ($val['sysmapid'] != 0) { $widget_fields[] = [ 'type' => ZBX_WIDGET_FIELD_TYPE_MAP, 'name' => $this->name.'.sysmapid.'.$index, 'value' => $val['sysmapid'] ]; } } } /** * Check and fix the tree of the maps. */ private static function validateNavTree(array $navtree_items, array &$errors): array { // Check for incorrect parent IDs. foreach ($navtree_items as $fieldid => &$navtree_item) { if ($navtree_item['parent'] != 0 && !array_key_exists($navtree_item['parent'], $navtree_items)) { $errors[] = _s('Incorrect value for field "%1$s": %2$s.', 'navtree.parent.'.$fieldid, _('reference to a non-existent tree element') ); $navtree_item['parent'] = 0; } } unset($navtree_item); // Find and fix circular dependencies. foreach ($navtree_items as $navtree_item) { $parentid = $navtree_item['parent']; $parentids = [$parentid => true]; while ($parentid != 0) { if (array_key_exists($navtree_items[$parentid]['parent'], $parentids)) { $errors[] = _s('Incorrect value for field "%1$s": %2$s.', 'navtree.parent.'.$parentid, _('circular dependency is not allowed') ); $navtree_items[$parentid]['parent'] = 0; } $parentid = $navtree_items[$parentid]['parent']; } } return $navtree_items; } }