summaryrefslogtreecommitdiffstats
path: root/application/forms/IcingaMultiEditForm.php
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--application/forms/IcingaMultiEditForm.php324
1 files changed, 324 insertions, 0 deletions
diff --git a/application/forms/IcingaMultiEditForm.php b/application/forms/IcingaMultiEditForm.php
new file mode 100644
index 0000000..4149a70
--- /dev/null
+++ b/application/forms/IcingaMultiEditForm.php
@@ -0,0 +1,324 @@
+<?php
+
+namespace Icinga\Module\Director\Forms;
+
+use Icinga\Module\Director\Data\Db\DbObject;
+use Icinga\Module\Director\Hook\IcingaObjectFormHook;
+use Icinga\Module\Director\Web\Form\IcingaObjectFieldLoader;
+use Icinga\Module\Director\Web\Form\DirectorObjectForm;
+use Icinga\Module\Director\Web\Form\QuickForm;
+use Zend_Form_Element as ZfElement;
+
+class IcingaMultiEditForm extends DirectorObjectForm
+{
+ /** @var DbObject[] */
+ private $objects;
+
+ private $elementGroupMap;
+
+ /** @var QuickForm */
+ private $relatedForm;
+
+ private $propertiesToPick;
+
+ public function setObjects($objects)
+ {
+ $this->objects = $objects;
+ $this->object = current($this->objects);
+ $this->db = $this->object()->getConnection();
+ return $this;
+ }
+
+ public function isMultiObjectForm()
+ {
+ return true;
+ }
+
+ public function pickElementsFrom(QuickForm $form, $properties)
+ {
+ $this->relatedForm = $form;
+ $this->propertiesToPick = $properties;
+ return $this;
+ }
+
+ public function setup()
+ {
+ $object = $this->object;
+
+ $loader = new IcingaObjectFieldLoader($object);
+ $loader->prepareElements($this);
+ $loader->addFieldsToForm($this);
+
+ if ($form = $this->relatedForm) {
+ if ($form instanceof DirectorObjectForm) {
+ $form->setDb($object->getConnection())
+ ->setObject($object);
+ }
+
+ $form->prepareElements();
+ } else {
+ $this->propertiesToPick = array();
+ }
+
+ foreach ($this->propertiesToPick as $property) {
+ if ($el = $form->getElement($property)) {
+ $this->makeVariants($el);
+ }
+ }
+
+ /** @var \Zend_Form_Element $el */
+ foreach ($this->getElements() as $el) {
+ $name = $el->getName();
+ if (substr($name, 0, 4) === 'var_') {
+ $this->makeVariants($el);
+ }
+ }
+
+ $this->setButtons();
+ }
+
+ public function onSuccess()
+ {
+ foreach ($this->getValues() as $key => $value) {
+ $this->setSubmittedMultiValue($key, $value);
+ }
+
+ $modified = $this->storeModifiedObjects();
+ if ($modified === 0) {
+ $msg = $this->translate('No object has been modified');
+ } elseif ($modified === 1) {
+ $msg = $this->translate('One object has been modified');
+ } else {
+ $msg = sprintf(
+ $this->translate('%d objects have been modified'),
+ $modified
+ );
+ }
+
+ $this->redirectOnSuccess($msg);
+ }
+
+ /**
+ * No default objects behaviour
+ */
+ protected function onRequest()
+ {
+ IcingaObjectFormHook::callOnSetup($this);
+ if ($this->hasBeenSent()) {
+ $this->handlePost();
+ }
+ }
+
+ protected function handlePost()
+ {
+ $this->callOnRequestCallables();
+ if ($this->shouldBeDeleted()) {
+ $this->deleteObjects();
+ }
+ }
+
+ protected function setSubmittedMultiValue($key, $value)
+ {
+ $parts = preg_split('/_/', $key);
+ $objectsSum = array_pop($parts);
+ $valueSum = array_pop($parts);
+ $property = implode('_', $parts);
+
+ if ($value === '') {
+ $value = null;
+ }
+
+ foreach ($this->getVariants($property) as $json => $objects) {
+ if ($valueSum !== sha1($json)) {
+ continue;
+ }
+
+ if ($objectsSum !== sha1(json_encode($objects))) {
+ continue;
+ }
+
+ if (substr($property, 0, 4) === 'var_') {
+ $property = 'vars.' . substr($property, 4);
+ }
+
+ foreach ($this->getObjects($objects) as $object) {
+ $object->$property = $value;
+ }
+ }
+ }
+
+ protected function storeModifiedObjects()
+ {
+ $modified = 0;
+ $store = $this->getDbObjectStore();
+ foreach ($this->objects as $object) {
+ if ($object->hasBeenModified()) {
+ $modified++;
+ $store->store($object);
+ }
+ }
+
+ return $modified;
+ }
+
+ protected function getDisplayGroupForElement(ZfElement $element)
+ {
+ if ($this->elementGroupMap === null) {
+ $this->resolveDisplayGroups();
+ }
+
+ $name = $element->getName();
+ if (array_key_exists($name, $this->elementGroupMap)) {
+ $groupName = $this->elementGroupMap[$name];
+
+ if ($group = $this->getDisplayGroup($groupName)) {
+ return $group;
+ } elseif ($this->relatedForm) {
+ return $this->stealDisplayGroup($groupName, $this->relatedForm);
+ }
+ }
+
+ return null;
+ }
+
+ protected function stealDisplayGroup($name, QuickForm $form)
+ {
+ if ($group = $form->getDisplayGroup($name)) {
+ $group = clone($group);
+ $group->setElements(array());
+ $this->_displayGroups[$name] = $group;
+ $this->_order[$name] = $group->getOrder();
+ $this->_orderUpdated = true;
+
+ return $group;
+ }
+
+ return null;
+ }
+
+ protected function resolveDisplayGroups()
+ {
+ $this->elementGroupMap = array();
+ if ($form = $this->relatedForm) {
+ $this->extractFormDisplayGroups($form);
+ }
+
+ $this->extractFormDisplayGroups($this);
+ }
+
+ protected function extractFormDisplayGroups(QuickForm $form)
+ {
+ /** @var \Zend_Form_DisplayGroup $group */
+ foreach ($form->getDisplayGroups() as $group) {
+ $groupName = $group->getName();
+ foreach ($group->getElements() as $name => $e) {
+ $this->elementGroupMap[$name] = $groupName;
+ }
+ }
+ }
+
+ protected function makeVariants(ZfElement $element)
+ {
+ $key = $element->getName();
+ $this->removeElement($key);
+ $label = $element->getLabel();
+ $group = $this->getDisplayGroupForElement($element);
+ $description = $element->getDescription();
+
+ foreach ($this->getVariants($key) as $json => $objects) {
+ $value = json_decode($json);
+ $checksum = sha1($json) . '_' . sha1(json_encode($objects));
+
+ $v = clone($element);
+ $v->setName($key . '_' . $checksum);
+ $v->setDescription($description . ' ' . $this->descriptionForObjects($objects));
+ $v->setLabel($label . $this->labelCount($objects));
+ $v->setValue($value);
+ if ($group) {
+ $group->addElement($v);
+ }
+ $this->addElement($v);
+ }
+ }
+
+ protected function getVariants($key)
+ {
+ $variants = array();
+ if (substr($key, 0, 4) === 'var_') {
+ $key = 'vars.' . substr($key, 4);
+ }
+
+ foreach ($this->objects as $name => $object) {
+ $value = json_encode($object->$key);
+ if (! array_key_exists($value, $variants)) {
+ $variants[$value] = array();
+ }
+
+ $variants[$value][] = $name;
+ }
+
+ foreach ($variants as & $objects) {
+ natsort($objects);
+ }
+
+ return $variants;
+ }
+
+ protected function descriptionForObjects($list)
+ {
+ return sprintf(
+ $this->translate('Changing this value affects %d object(s): %s'),
+ count($list),
+ implode(', ', $list)
+ );
+ }
+
+ protected function labelCount($list)
+ {
+ return ' (' . count($list) . ')';
+ }
+
+ protected function db()
+ {
+ if ($this->db === null) {
+ $this->db = $this->object()->getConnection();
+ }
+
+ return $this->db;
+ }
+
+ public function getObjects($names = null)
+ {
+ if ($names === null) {
+ return $this->objects;
+ }
+
+ $res = array();
+
+ foreach ($names as $name) {
+ $res[$name] = $this->objects[$name];
+ }
+
+ return $res;
+ }
+
+ protected function deleteObjects()
+ {
+ $msg = sprintf(
+ '%d objects of type "%s" have been removed',
+ count($this->objects),
+ $this->translate($this->object->getShortTableName())
+ );
+
+ $store = $this->getDbObjectStore();
+ foreach ($this->objects as $object) {
+ $store->delete($object);
+ }
+
+ if ($this->listUrl) {
+ $this->setSuccessUrl($this->listUrl);
+ }
+
+ $this->redirectOnSuccess($msg);
+ }
+}