mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-14 08:34:39 +00:00
(mvc) improve API for array type model objects
Integrate uuid generation into the core of the model system so items are uniquely identified and can be directly accessed using their uuids.
For example:
// set recurring pipe item to 1001
$model->setNodeByReference('pipes.pipe.86f19d48-bc91-4c70-a81c-e05cdd3a4372.queue', "1001");
// echo the contents back
echo $model->getNodeByReference('pipes.pipe.86f19d48-bc91-4c70-a81c-e05cdd3a4372.queue');
This commit is contained in:
parent
69d4aa9f11
commit
ceda9d08dd
@ -153,19 +153,26 @@ abstract class BaseModel
|
||||
if ($fieldObject instanceof ArrayField) {
|
||||
// handle Array types, recurring items
|
||||
if ($config_section_data != null) {
|
||||
$counter = 0 ;
|
||||
foreach ($config_section_data as $conf_section) {
|
||||
// Array items are identified by a UUID, read from attribute or create a new one
|
||||
if (isset($conf_section->attributes()->uuid)) {
|
||||
$tagUUID = $conf_section->attributes()['uuid']->__toString();
|
||||
} else {
|
||||
$tagUUID = $internal_data->generateUUID();
|
||||
}
|
||||
|
||||
// iterate array items from config data
|
||||
$child_node = new ContainerField($fieldObject->__reference . "." . ($counter++), $tagName);
|
||||
$child_node = new ContainerField($fieldObject->__reference . "." . $tagUUID, $tagName);
|
||||
$this->parseXml($xmlNode, $conf_section, $child_node);
|
||||
$fieldObject->addChildNode(null, $child_node);
|
||||
$fieldObject->addChildNode($tagUUID, $child_node);
|
||||
}
|
||||
} else {
|
||||
// There's no content in config.xml for this array node.
|
||||
$child_node = new ContainerField($fieldObject->__reference . ".0", $tagName);
|
||||
$tagUUID = $internal_data->generateUUID();
|
||||
$child_node = new ContainerField($fieldObject->__reference . ".".$tagUUID, $tagName);
|
||||
$child_node->setInternalIsVirtual();
|
||||
$this->parseXml($xmlNode, $config_section_data, $child_node);
|
||||
$fieldObject->addChildNode(null, $child_node);
|
||||
$fieldObject->addChildNode($tagUUID, $child_node);
|
||||
}
|
||||
} else {
|
||||
// All other node types (Text,Email,...)
|
||||
|
||||
@ -34,27 +34,11 @@ namespace OPNsense\Base\FieldTypes;
|
||||
*/
|
||||
class ArrayField extends BaseField
|
||||
{
|
||||
/**
|
||||
* @var int item index
|
||||
*/
|
||||
private $internalArrayCounter = 0 ;
|
||||
|
||||
/**
|
||||
* @var null|BaseField node to use for copying
|
||||
*/
|
||||
private $internalTemplateNode = null;
|
||||
|
||||
/**
|
||||
* add Childnode (list), ignore the name of this item
|
||||
* @param string $name property name
|
||||
* @param BaseField $node content (must be of type BaseField)
|
||||
*/
|
||||
public function addChildNode($name, $node)
|
||||
{
|
||||
$this->internalChildnodes[(string)$this->internalArrayCounter] = $node;
|
||||
$this->internalArrayCounter++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy first node pointer as template node to make sure we always have a template to create new nodes from.
|
||||
* If the first node is virtual (no source data), remove that from the list.
|
||||
@ -63,20 +47,13 @@ class ArrayField extends BaseField
|
||||
{
|
||||
// always make sure there's a node to copy our structure from
|
||||
if ($this->internalTemplateNode ==null) {
|
||||
$this->internalTemplateNode = $this->internalChildnodes["0"];
|
||||
$firstKey = array_keys($this->internalChildnodes)[0];
|
||||
$this->internalTemplateNode = $this->internalChildnodes[$firstKey];
|
||||
/**
|
||||
* if first node is empty, remove reference node.
|
||||
*/
|
||||
if ($this->internalChildnodes["0"]->getInternalIsVirtual()) {
|
||||
unset($this->internalChildnodes["0"]);
|
||||
$this->internalArrayCounter--;
|
||||
}
|
||||
}
|
||||
|
||||
// check if all children have a uuid, generate one if missing
|
||||
foreach ($this->internalChildnodes as $nodeKey => $node) {
|
||||
if (!array_key_exists('uuid', $node->getAttributes())) {
|
||||
$node->setAttributeValue("uuid", $this->generateUUID());
|
||||
if ($this->internalChildnodes[$firstKey]->getInternalIsVirtual()) {
|
||||
unset($this->internalChildnodes[$firstKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -97,8 +74,9 @@ class ArrayField extends BaseField
|
||||
$new_record[$key] = clone $node ;
|
||||
}
|
||||
|
||||
$nodeUUID = $this->generateUUID();
|
||||
$container_node = new ContainerField(
|
||||
$this->__reference . "." . $this->internalArrayCounter,
|
||||
$this->__reference . "." . $nodeUUID,
|
||||
$this->internalXMLTagName
|
||||
);
|
||||
|
||||
@ -110,17 +88,17 @@ class ArrayField extends BaseField
|
||||
}
|
||||
|
||||
// make sure we have a UUID on repeating child items
|
||||
$container_node->setAttributeValue("uuid", $this->generateUUID());
|
||||
$container_node->setAttributeValue("uuid", $nodeUUID);
|
||||
|
||||
// add node to this object
|
||||
$this->addChildNode(null, $container_node);
|
||||
$this->addChildNode($nodeUUID, $container_node);
|
||||
|
||||
return $container_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove item by id (number)
|
||||
* @param $index index number
|
||||
* @param string $index index number
|
||||
*/
|
||||
public function del($index)
|
||||
{
|
||||
@ -129,38 +107,43 @@ class ArrayField extends BaseField
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* search child item by UUID
|
||||
* @param $uuid item uuid
|
||||
* @return BaseField|null
|
||||
* @param string|array $fieldNames sort by fieldname
|
||||
* @param bool $descending sort descending
|
||||
* @return array
|
||||
*/
|
||||
public function findByUUID($uuid)
|
||||
public function sortedBy($fieldNames, $descending = false)
|
||||
{
|
||||
foreach ($this->internalChildnodes as $nodeKey => $node) {
|
||||
$nodeAttr = $node->getAttributes();
|
||||
if (array_key_exists('uuid', $nodeAttr) && $nodeAttr['uuid'] == $uuid) {
|
||||
return $node;
|
||||
}
|
||||
// reserve at least X number of characters for every field to improve sorting of multiple fields
|
||||
$MAX_KEY_LENGTH = 30;
|
||||
|
||||
// fieldnames may be a list or a single item, always convert to a list
|
||||
if (!is_array($fieldNames)) {
|
||||
$fieldNames = array($fieldNames);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* search child item by UUID
|
||||
* @param $uuid item uuid
|
||||
* @return bool
|
||||
*/
|
||||
public function delByUUID($uuid)
|
||||
{
|
||||
// collect sortable data as key/value store
|
||||
$sortedData=array();
|
||||
foreach ($this->internalChildnodes as $nodeKey => $node) {
|
||||
$nodeAttr = $node->getAttributes();
|
||||
if (array_key_exists('uuid', $nodeAttr) && $nodeAttr['uuid'] == $uuid) {
|
||||
unset($this->internalChildnodes[$nodeKey]);
|
||||
return true;
|
||||
// populate sort key
|
||||
$sortKey = '';
|
||||
foreach ($fieldNames as $fieldName) {
|
||||
if (array_key_exists($fieldName, $node->internalChildnodes)) {
|
||||
$sortKey .= sprintf("%".$MAX_KEY_LENGTH."s ,", $node->$fieldName) ;
|
||||
}
|
||||
}
|
||||
$sortKey .= $nodeKey; // prevent overwrite of duplicates
|
||||
$sortedData[$sortKey] = $node ;
|
||||
}
|
||||
return false;
|
||||
|
||||
// sort by key on ascending or descending order
|
||||
if (!$descending) {
|
||||
ksort($sortedData);
|
||||
} else {
|
||||
krsort($sortedData);
|
||||
}
|
||||
|
||||
return array_values($sortedData);
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ abstract class BaseField
|
||||
/**
|
||||
* @return string uuid v4 number
|
||||
*/
|
||||
protected function generateUUID()
|
||||
public function generateUUID()
|
||||
{
|
||||
return sprintf(
|
||||
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user