Commit 1a5f089e authored by Ad Schellevis's avatar Ad Schellevis

* implement add/del for array types (not recursive)

* added save/backup actions on config class
parent 2798c28f
...@@ -34,6 +34,16 @@ namespace OPNsense\Base\FieldTypes; ...@@ -34,6 +34,16 @@ namespace OPNsense\Base\FieldTypes;
*/ */
class ArrayField extends BaseField 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 * add Childnode (list), ignore the name of this item
* @param string $name property name * @param string $name property name
...@@ -41,6 +51,71 @@ class ArrayField extends BaseField ...@@ -41,6 +51,71 @@ class ArrayField extends BaseField
*/ */
public function addChildNode($name, $node) public function addChildNode($name, $node)
{ {
$this->internalChildnodes[] = $node; $this->internalChildnodes[(string)$this->internalArrayCounter] = $node;
$this->internalArrayCounter++;
}
/**
*
*/
private function internalCopyStructure()
{
// always make sure there's a node to copy our structure from
if ($this->internalTemplateNode ==null) {
$this->internalTemplateNode = $this->internalChildnodes["0"];
/**
* if first node is empty, remove reference node.
*/
if ($this->internalChildnodes["0"]->getInternalIsVirtual()) {
unset($this->internalChildnodes["0"]);
$this->internalArrayCounter--;
}
}
}
/**
* add new node containing the types from the first node (copy)
* @return ContainerField created node
* @throws \Exception
*/
public function add()
{
$this->internalCopyStructure();
$new_record = array();
foreach ($this->internalTemplateNode->__items as $key => $node) {
if ($node->isContainer()) {
// validate child nodes, nesting not supported in this version.
throw new \Exception("Unsupported copy, Array doesn't support nesting.");
}
$new_record[$key] = clone $node ;
}
$container_node = new ContainerField(
$this->__reference . "." . $this->internalArrayCounter,
$this->internalXMLTagName
);
foreach ($new_record as $key => $node) {
$node->setInternalReference($container_node->__reference.".".$key);
$container_node->addChildNode($key, $node);
}
// add node to this object
$this->addChildNode(null, $container_node);
return $container_node;
}
/**
* remove item by id (number)
* @param $index index number
*/
public function del($index)
{
$this->internalCopyStructure();
if (array_key_exists((string)$index, $this->internalChildnodes)) {
unset($this->internalChildnodes[$index]);
}
} }
} }
...@@ -54,7 +54,7 @@ abstract class BaseField ...@@ -54,7 +54,7 @@ abstract class BaseField
/** /**
* @var string direct reference to this field in the model object * @var string direct reference to this field in the model object
*/ */
protected $internalReference = ""; protected $internalReference = null;
/** /**
* @var string tag name for this object, either the last part of the reference. * @var string tag name for this object, either the last part of the reference.
...@@ -96,6 +96,30 @@ abstract class BaseField ...@@ -96,6 +96,30 @@ abstract class BaseField
$this->internalXMLTagName = $tagname; $this->internalXMLTagName = $tagname;
} }
/**
* reset on clone
*/
public function __clone()
{
$this->internalIsVirtual = false ;
$this->internalValue = "";
$this->internalReference = null;
}
/**
* change internal reference, if set it can't be changed for safety purposes.
* @param $ref internal reference
* @throws \Exception change exception
*/
public function setInternalReference($ref)
{
if ($this->internalReference == null) {
$this->internalReference = $ref;
} else {
throw new \Exception("cannot change internal reference");
}
}
/** /**
* Add a childnode to this node. * Add a childnode to this node.
* @param string $name property name * @param string $name property name
...@@ -143,6 +167,8 @@ abstract class BaseField ...@@ -143,6 +167,8 @@ abstract class BaseField
{ {
if (array_key_exists($name, $this->internalChildnodes)) { if (array_key_exists($name, $this->internalChildnodes)) {
$this->internalChildnodes[$name]->setValue($value); $this->internalChildnodes[$name]->setValue($value);
} else {
throw new \InvalidArgumentException($name." not an attribute of ". $this->internalReference);
} }
} }
...@@ -188,6 +214,14 @@ abstract class BaseField ...@@ -188,6 +214,14 @@ abstract class BaseField
$this->internalIsVirtual = true; $this->internalIsVirtual = true;
} }
/**
* @return bool is virtual node
*/
public function getInternalIsVirtual()
{
return $this->internalIsVirtual;
}
/** /**
* getter for internal tag name * getter for internal tag name
* @return null|string xml tagname to use * @return null|string xml tagname to use
......
...@@ -48,7 +48,7 @@ class EmailField extends BaseField ...@@ -48,7 +48,7 @@ class EmailField extends BaseField
public function getValidators() public function getValidators()
{ {
if ($this->internalValidationMessage == null) { if ($this->internalValidationMessage == null) {
$msg = "email address invalid for " . $this->internalReference; $msg = "email address invalid" ;
} else { } else {
$msg = $this->internalValidationMessage; $msg = $this->internalValidationMessage;
} }
...@@ -58,6 +58,5 @@ class EmailField extends BaseField ...@@ -58,6 +58,5 @@ class EmailField extends BaseField
// empty field and not required, skip this validation. // empty field and not required, skip this validation.
return array(); return array();
} }
} }
} }
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
*/ */
namespace OPNsense\Base\FieldTypes; namespace OPNsense\Base\FieldTypes;
use Phalcon\Validation\Validator\Regex;
/** /**
* Class TextField * Class TextField
* @package OPNsense\Base\FieldTypes * @package OPNsense\Base\FieldTypes
...@@ -52,4 +54,22 @@ class TextField extends BaseField ...@@ -52,4 +54,22 @@ class TextField extends BaseField
{ {
$this->internalMask = $value ; $this->internalMask = $value ;
} }
/**
* @return array returns Text/regex validator
*/
public function getValidators()
{
if ($this->internalValidationMessage == null) {
$msg = "text validation error" ;
} else {
$msg = $this->internalValidationMessage;
}
if (($this->internalIsRequired == true || $this->internalValue != null) && $this->internalMask != null) {
return array(new Regex(array('message' => $msg,'pattern'=>trim($this->internalMask))));
} else {
// empty field and not required, skip this validation.
return array();
}
}
} }
...@@ -185,7 +185,8 @@ class Config extends Singleton ...@@ -185,7 +185,8 @@ class Config extends Singleton
} }
/** /**
* @return mixed return xml text representation of this config * return xml text representation of this config
* @return mixed string interpretation of this object
*/ */
public function __toString() public function __toString()
{ {
...@@ -198,4 +199,55 @@ class Config extends Singleton ...@@ -198,4 +199,55 @@ class Config extends Singleton
return $dom->saveXML(); return $dom->saveXML();
} }
/**
* backup current (running) config
* @param string|null $message log message
*/
private function backup($message)
{
$target_dir = dirname($this->config_file)."/backup/";
$target_filename = "config-".time().".xml";
if (file_exists($target_dir)) {
copy($this->config_file, $target_dir.$target_filename);
}
}
/**
* save config to filesystem
* @param string|null $message log message
* @param bool $nobackup do not backup current config
* @throws ConfigException
*/
public function save($message = null, $nobackup = false)
{
$xml_text = $this->__toString();
if ($nobackup == false) {
$this->backup($message);
}
// save configuration, try to obtain a lock before doing so.
$target_filename = $this->config_file;
if (file_exists($target_filename)) {
$fp = fopen($target_filename, "r+");
} else {
// apparently we're missing the config, not expected but open a new one.
$fp = fopen($target_filename, "w+");
}
if (flock($fp, LOCK_EX)) {
// lock aquired, truncate and write new data
ftruncate($fp, 0);
fwrite($fp, $xml_text);
// flush and unlock
fflush($fp);
flock($fp, LOCK_UN);
} else {
throw new ConfigException("Unable to lock config");
}
}
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
</description> </description>
<items> <items>
<tag1 type="TextField"> <tag1 type="TextField">
<Mask>[A-Z]</Mask> <Mask>/^([A-Z,1-9]){0,10}$/</Mask>
</tag1> </tag1>
<tagX> <tagX>
<tag1 type="EmailField"> <tag1 type="EmailField">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment