diff --git a/lib/Controller/AggregatorController.php b/lib/Controller/AggregatorController.php index 2b90637..32ff332 100644 --- a/lib/Controller/AggregatorController.php +++ b/lib/Controller/AggregatorController.php @@ -39,8 +39,13 @@ class AggregatorController extends EntityController { */ public function get($identifier = NULL) { $aggregator = parent::get($identifier); - - if ($aggregator instanceof Model\Aggregator) { + + if (is_array($aggregator)) { // filter public entities + return array('channels' => array_values(array_filter($aggregator['entities'], function($agg) { + return ($agg instanceof Model\Aggregator); + }))); + } + else if ($aggregator instanceof Model\Aggregator) { return $aggregator; } else { @@ -64,7 +69,13 @@ class AggregatorController extends EntityController { } } else { // create new aggregator - $aggregator = new Model\Aggregator('group'); // TODO support for other aggregator types + $type = $this->view->request->getParameter('type'); + + if (!isset($ype)) { + $type = 'group'; + } + + $aggregator = new Model\Aggregator($type); $this->setProperties($aggregator, $this->view->request->getParameters()); $this->em->persist($aggregator); diff --git a/lib/Controller/ChannelController.php b/lib/Controller/ChannelController.php index 82a644f..aabcf80 100644 --- a/lib/Controller/ChannelController.php +++ b/lib/Controller/ChannelController.php @@ -24,8 +24,8 @@ namespace Volkszaehler\Controller; use Volkszaehler\Definition; - use Volkszaehler\Model; +use Volkszaehler\Util; /** * Channel controller @@ -39,8 +39,13 @@ class ChannelController extends EntityController { */ public function get($identifier = NULL) { $channel = parent::get($identifier); - - if ($channel instanceof Model\Channel) { + + if (is_array($channel)) { // filter public entities + return array('channels' => array_values(array_filter($channel['entities'], function($ch) { + return ($ch instanceof Model\Channel); + }))); + } + else if ($channel instanceof Model\Channel) { return $channel; } else { @@ -52,7 +57,13 @@ class ChannelController extends EntityController { * Add channel */ public function add() { - $channel = new Model\Channel($this->view->request->getParameter('type')); + $type = $this->view->request->getParameter('type'); + + if (!isset($type)) { + throw new \Exception('Missing entity type'); + } + + $channel = new Model\Channel($type); $this->setProperties($channel, $this->view->request->getParameters()); $this->em->persist($channel); $this->em->flush(); diff --git a/lib/Controller/EntityController.php b/lib/Controller/EntityController.php index eb00692..416a8b8 100644 --- a/lib/Controller/EntityController.php +++ b/lib/Controller/EntityController.php @@ -125,16 +125,23 @@ class EntityController extends Controller { * Update/set/delete properties of entities */ protected function setProperties(Model\Entity $entity, $parameters) { - foreach ($parameters as $parameter => $value) { - if (Definition\PropertyDefinition::exists($parameter)) { - if ($value == '') { - $entity->unsetProperty($parameter, $this->em); - } - else { - $entity->setProperty($parameter, $value); - } + foreach ($parameters as $key => $value) { + if (in_array($key, array('operation', 'type'))) { + continue; // skip generic parameters + } + else if (!Definition\PropertyDefinition::exists($key)) { + throw new \Exception('Unknown property'); + } + + if ($value == '') { // dont use empty() because it also matches 0 + $entity->deleteProperty($key); + } + else { + $entity->setProperty($key, $value); } } + + $entity->checkProperties(); } /** @@ -152,8 +159,8 @@ class EntityController extends Controller { $i = 0; $sqlWhere = array(); $sqlParams = array(); - foreach ($properties as $property => $value) { - switch (Definition\PropertyDefinition::get($property)->getType()) { + foreach ($properties as $key => $value) { + switch (Definition\PropertyDefinition::get($key)->getType()) { case 'string': case 'text': case 'multiple': @@ -165,7 +172,7 @@ class EntityController extends Controller { } $sqlWhere[] = 'EXISTS (SELECT p' . $i . ' FROM \Volkszaehler\Model\Property p' . $i . ' WHERE p' . $i . '.key = :key' . $i . ' AND p' . $i . '.value = :value' . $i . ' AND p' . $i . '.entity = a)'; $sqlParams += array( - 'key' . $i => $property, + 'key' . $i => $key, 'value' . $i => $value ); $i++; diff --git a/lib/Definition/PropertyDefinition.json b/lib/Definition/PropertyDefinition.json index 3743f81..7c42f9d 100644 --- a/lib/Definition/PropertyDefinition.json +++ b/lib/Definition/PropertyDefinition.json @@ -41,7 +41,7 @@ "name" : "description", "type" : "text", "pattern" : "/[a-z0-9\\s]/", - "max" : 255, // TODO use "text" type for unlimited descriptions => PropertyModel + "min" : "3", "translation" : { "de" : "Beschreibung", "en" : "Description" diff --git a/lib/Model/Aggregator.php b/lib/Model/Aggregator.php index e092155..e4beced 100644 --- a/lib/Model/Aggregator.php +++ b/lib/Model/Aggregator.php @@ -50,10 +50,10 @@ class Aggregator extends Entity { protected $children = NULL; /** - * Construct + * Constructor */ - public function __construct($properties = array()) { - parent::__construct($properties); + public function __construct($type) { + parent::__construct($type); $this->children = new ArrayCollection(); } diff --git a/lib/Model/Channel.php b/lib/Model/Channel.php index caaa496..3f246b3 100644 --- a/lib/Model/Channel.php +++ b/lib/Model/Channel.php @@ -35,7 +35,7 @@ use Doctrine\Common\Collections\ArrayCollection; */ class Channel extends Entity { /** - * @OneToMany(targetEntity="Data", mappedBy="channel", cascade={"remove", "persist"}) + * @OneToMany(targetEntity="Data", mappedBy="channel", cascade={"persist"}, orphanRemoval=true) * @OrderBy({"timestamp" = "ASC"}) */ protected $data = NULL; @@ -43,8 +43,8 @@ class Channel extends Entity { /** * Constructor */ - public function __construct($type, $properties = array()) { - parent::__construct($type, $properties); + public function __construct($type) { + parent::__construct($type); $this->data = new ArrayCollection(); $this->groups = new ArrayCollection(); diff --git a/lib/Model/Entity.php b/lib/Model/Entity.php index fcc6ead..25197da 100644 --- a/lib/Model/Entity.php +++ b/lib/Model/Entity.php @@ -59,7 +59,7 @@ abstract class Entity { protected $type; /** - * @OneToMany(targetEntity="Property", mappedBy="entity", cascade={"remove", "persist"}) + * @OneToMany(targetEntity="Property", mappedBy="entity", cascade={"persist"}, orphanRemoval=true) * @OrderBy({"key" = "ASC"}) */ protected $properties = NULL; @@ -80,7 +80,7 @@ abstract class Entity { } $this->type = $type; - $this->uuid = (string) Util\UUID::mint(); + $this->uuid = (string) Util\UUID::mint(); // generate random UUID $this->properties = new Collections\ArrayCollection(); $this->parents = new Collections\ArrayCollection(); @@ -101,7 +101,7 @@ abstract class Entity { } if (count($invalidProperties) > 0) { - throw new \Exception('Propert' . ((count($invalidProperties) == 1) ? 'y' : 'ies') . ' "' . implode(', ', $invalidProperties) . '" ' . ((count($invalidProperties) == 1) ? 'is' : 'are') . ' not allowed for entity "' . $this->getType() . '"'); + throw new \Exception('Propert' . ((count($invalidProperties) == 1) ? 'y' : 'ies') . ' \'' . implode(', ', $invalidProperties) . '\' ' . ((count($invalidProperties) == 1) ? 'is' : 'are') . ' not valid for entity \'' . $this->getType() . '\''); } } @@ -122,10 +122,6 @@ abstract class Entity { * @return array */ public function getProperties($prefix = NULL) { - /*$this->properties->filter(function($property) { - return substr($property->getKey(), 0, strlen($prefix)) == $prefix; - })->toArray();*/ - $properties = array(); foreach ($this->properties as $property) { if (substr($property->getKey(), 0, strlen($prefix)) == $prefix) { @@ -137,6 +133,7 @@ abstract class Entity { } /** + * Find property by key * * @param string $key * @return Model\Property @@ -147,10 +144,12 @@ abstract class Entity { return $property; } } + + return FALSE; // not found } /** - * Set property + * Set property by key/value * * @param string $key name of the property * @param mixed $value of the property @@ -171,9 +170,13 @@ abstract class Entity { * @param string $name of the property * @param Doctrine\EntityManager $em */ - public function unsetProperty($key, ORM\EntityManager $em) { + public function deleteProperty($key) { $property = $this->findProperty($key); - $em->remove($property); + + if (!$property) { + throw new \Exception('Property not found'); + } + $this->properties->removeElement($property); } diff --git a/lib/Model/Property.php b/lib/Model/Property.php index 070d350..a0c9cff 100644 --- a/lib/Model/Property.php +++ b/lib/Model/Property.php @@ -58,7 +58,7 @@ class Property { */ protected $key; - /** @Column(type="string", nullable=false) */ + /** @Column(type="text", nullable=false) */ protected $value; /** @ManyToOne(targetEntity="Entity", inversedBy="properties") */ @@ -74,6 +74,8 @@ class Property { $this->entity = $entity; $this->key = $key; $this->value = $value; + + $this->validate(); } /** @@ -104,32 +106,13 @@ class Property { */ public function validate() { if (!Definition\PropertyDefinition::exists($this->key)) { - throw new \Exception('Invalid property key: ' . $this->key); + throw new \Exception('Invalid property'); } $this->cast(); // TODO not safe if (!$this->getDefinition()->validateValue($this->value)) { - throw new \Exception('Invalid property value: ' . $this->value); - } - } - - /** - * @PreRemove - * @todo blocks removal of entity - */ - public function checkRemove() { - if (in_array($this->key, $this->entity->getDefinition()->getRequiredProperties())) { - throw new \Exception($this->key . ' is a required property for the entity: ' . $this->entity->getType()); - } - } - - /** - * @PrePersist - */ - public function checkPersist() { - if (!in_array($this->key, $this->entity->getDefinition()->getValidProperties())) { - throw new \Exception($this->key . ' is not a valid property for the entity: ' . $this->entity->getType()); + throw new \Exception('Invalid property value'); } }