summaryrefslogtreecommitdiffstats
path: root/library/Director/Objects/DirectorDatafield.php
diff options
context:
space:
mode:
Diffstat (limited to 'library/Director/Objects/DirectorDatafield.php')
-rw-r--r--library/Director/Objects/DirectorDatafield.php344
1 files changed, 344 insertions, 0 deletions
diff --git a/library/Director/Objects/DirectorDatafield.php b/library/Director/Objects/DirectorDatafield.php
new file mode 100644
index 0000000..84db068
--- /dev/null
+++ b/library/Director/Objects/DirectorDatafield.php
@@ -0,0 +1,344 @@
+<?php
+
+namespace Icinga\Module\Director\Objects;
+
+use Icinga\Module\Director\Core\Json;
+use Icinga\Module\Director\Data\Db\DbObjectWithSettings;
+use Icinga\Module\Director\Db;
+use Icinga\Module\Director\DirectorObject\Automation\CompareBasketObject;
+use Icinga\Module\Director\Exception\DuplicateKeyException;
+use Icinga\Module\Director\Forms\IcingaServiceForm;
+use Icinga\Module\Director\Hook\DataTypeHook;
+use Icinga\Module\Director\Resolver\OverriddenVarsResolver;
+use Icinga\Module\Director\Web\Form\DirectorObjectForm;
+use InvalidArgumentException;
+use Zend_Form_Element as ZfElement;
+
+class DirectorDatafield extends DbObjectWithSettings
+{
+ protected $table = 'director_datafield';
+
+ protected $keyName = 'id';
+
+ protected $autoincKeyName = 'id';
+
+ protected $defaultProperties = [
+ 'id' => null,
+ 'category_id' => null,
+ 'varname' => null,
+ 'caption' => null,
+ 'description' => null,
+ 'datatype' => null,
+ 'format' => null,
+ ];
+
+ protected $relations = [
+ 'category' => 'DirectorDatafieldCategory'
+ ];
+
+ protected $settingsTable = 'director_datafield_setting';
+
+ protected $settingsRemoteId = 'datafield_id';
+
+ /** @var DirectorDatafieldCategory|null */
+ private $category;
+
+ private $object;
+
+ public static function fromDbRow($row, Db $connection)
+ {
+ $obj = static::create((array) $row, $connection);
+ $obj->loadedFromDb = true;
+ // TODO: $obj->setUnmodified();
+ $obj->hasBeenModified = false;
+ $obj->modifiedProperties = array();
+ $settings = $obj->getSettings();
+ // TODO: eventually prefetch
+ $obj->onLoadFromDb();
+
+ // Restoring values eventually destroyed by onLoadFromDb
+ foreach ($settings as $key => $value) {
+ $obj->settings[$key] = $value;
+ }
+
+ return $obj;
+ }
+
+ public function hasCategory()
+ {
+ return $this->category !== null || $this->get('category_id') !== null;
+ }
+
+ /**
+ * @return DirectorDatafieldCategory|null
+ * @throws \Icinga\Exception\NotFoundError
+ */
+ public function getCategory()
+ {
+ if ($this->category) {
+ return $this->category;
+ } elseif ($id = $this->get('category_id')) {
+ return DirectorDatafieldCategory::loadWithAutoIncId($id, $this->getConnection());
+ } else {
+ return null;
+ }
+ }
+
+ public function getCategoryName()
+ {
+ $category = $this->getCategory();
+ if ($category === null) {
+ return null;
+ } else {
+ return $category->get('category_name');
+ }
+ }
+
+ public function setCategory($category)
+ {
+ if ($category === null) {
+ $this->category = null;
+ $this->set('category_id', null);
+ } elseif ($category instanceof DirectorDatafieldCategory) {
+ if ($category->hasBeenLoadedFromDb()) {
+ $this->set('category_id', $category->get('id'));
+ }
+ $this->category = $category;
+ } else {
+ if (DirectorDatafieldCategory::exists($category, $this->getConnection())) {
+ $this->setCategory(DirectorDatafieldCategory::load($category, $this->getConnection()));
+ } else {
+ $this->setCategory(DirectorDatafieldCategory::create([
+ 'category_name' => $category
+ ], $this->getConnection()));
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * @return object
+ * @throws \Icinga\Exception\NotFoundError
+ */
+ public function export()
+ {
+ $plain = (object) $this->getProperties();
+ $plain->originalId = $plain->id;
+ unset($plain->id);
+ $plain->settings = (object) $this->getSettings();
+
+ if (property_exists($plain->settings, 'datalist_id')) {
+ $plain->settings->datalist = DirectorDatalist::loadWithAutoIncId(
+ $plain->settings->datalist_id,
+ $this->getConnection()
+ )->get('list_name');
+ unset($plain->settings->datalist_id);
+ }
+ if (property_exists($plain, 'category_id')) {
+ $plain->category = $this->getCategoryName();
+ unset($plain->category_id);
+ }
+
+ return $plain;
+ }
+
+ /**
+ * @param $plain
+ * @param Db $db
+ * @param bool $replace
+ * @return DirectorDatafield
+ * @throws \Icinga\Exception\NotFoundError
+ */
+ public static function import($plain, Db $db, $replace = false)
+ {
+ $properties = (array) $plain;
+ if (isset($properties['originalId'])) {
+ $id = $properties['originalId'];
+ unset($properties['originalId']);
+ } else {
+ $id = null;
+ }
+
+ if (isset($properties['settings']->datalist)) {
+ // Just try to load the list, import should fail if missing
+ $list = DirectorDatalist::load(
+ $properties['settings']->datalist,
+ $db
+ );
+ } else {
+ $list = null;
+ }
+
+ $compare = Json::decode(Json::encode($properties));
+ if ($id && static::exists($id, $db)) {
+ $existing = static::loadWithAutoIncId($id, $db);
+ $existingProperties = (array) $existing->export();
+ unset($existingProperties['originalId']);
+ if (CompareBasketObject::equals((object) $compare, (object) $existingProperties)) {
+ return $existing;
+ }
+ }
+
+ if ($list) {
+ unset($properties['settings']->datalist);
+ $properties['settings']->datalist_id = $list->get('id');
+ }
+
+ $dba = $db->getDbAdapter();
+ $query = $dba->select()
+ ->from('director_datafield')
+ ->where('varname = ?', $plain->varname);
+ $candidates = DirectorDatafield::loadAll($db, $query);
+
+ foreach ($candidates as $candidate) {
+ $export = $candidate->export();
+ unset($export->originalId);
+ CompareBasketObject::normalize($export);
+ if (CompareBasketObject::equals($export, $compare)) {
+ return $candidate;
+ }
+ }
+
+ return static::create($properties, $db);
+ }
+
+ protected function beforeStore()
+ {
+ if ($this->category) {
+ if (!$this->category->hasBeenLoadedFromDb()) {
+ throw new \RuntimeException('Trying to store a datafield with an unstored Category');
+ }
+ $this->set('category_id', $this->category->get('id'));
+ }
+ }
+
+ protected function setObject(IcingaObject $object)
+ {
+ $this->object = $object;
+ }
+
+ protected function getObject()
+ {
+ return $this->object;
+ }
+
+ public function getFormElement(DirectorObjectForm $form, $name = null)
+ {
+ $className = $this->get('datatype');
+
+ if ($name === null) {
+ $name = 'var_' . $this->get('varname');
+ }
+
+ if (! class_exists($className)) {
+ $form->addElement('text', $name, array('disabled' => 'disabled'));
+ $el = $form->getElement($name);
+ $msg = $form->translate('Form element could not be created, %s is missing');
+ $el->addError(sprintf($msg, $className));
+ return $el;
+ }
+
+ /** @var DataTypeHook $dataType */
+ $dataType = new $className;
+ $dataType->setSettings($this->getSettings());
+ $el = $dataType->getFormElement($name, $form);
+
+ if ($this->getSetting('icinga_type') !== 'command'
+ && $this->getSetting('is_required') === 'y'
+ ) {
+ $el->setRequired(true);
+ }
+ if ($caption = $this->get('caption')) {
+ $el->setLabel($caption);
+ }
+
+ if ($description = $this->get('description')) {
+ $el->setDescription($description);
+ }
+
+ $this->applyObjectData($el, $form);
+
+ return $el;
+ }
+
+ protected function applyObjectData(ZfElement $el, DirectorObjectForm $form)
+ {
+ $object = $form->getObject();
+ if (! ($object instanceof IcingaObject)) {
+ return;
+ }
+ if ($object->isTemplate()) {
+ $el->setRequired(false);
+ }
+
+ $varName = $this->get('varname');
+ $inherited = $origin = null;
+
+ if ($form instanceof IcingaServiceForm && $form->providesOverrides()) {
+ $resolver = new OverriddenVarsResolver($form->getDb());
+ $vars = $resolver->fetchForServiceName($form->getHost(), $object->getObjectName());
+ foreach ($vars as $host => $values) {
+ if (\property_exists($values, $varName)) {
+ $inherited = $values->$varName;
+ $origin = $host;
+ }
+ }
+ }
+
+ if ($inherited === null) {
+ $inherited = $object->getInheritedVar($varName);
+ if (null !== $inherited) {
+ $origin = $object->getOriginForVar($varName);
+ }
+ }
+
+ if ($inherited === null) {
+ $cmd = $this->eventuallyGetResolvedCommandVar($object, $varName);
+ if ($cmd !== null) {
+ list($inherited, $origin) = $cmd;
+ }
+ }
+
+ if ($inherited !== null) {
+ $form->setInheritedValue($el, $inherited, $origin);
+ }
+ }
+
+ protected function eventuallyGetResolvedCommandVar(IcingaObject $object, $varName)
+ {
+ if (! $object->hasRelation('check_command')) {
+ return null;
+ }
+
+ // TODO: Move all of this elsewhere and test it
+ try {
+ /** @var IcingaCommand $command */
+ $command = $object->getResolvedRelated('check_command');
+ if ($command === null) {
+ return null;
+ }
+ $inherited = $command->vars()->get($varName);
+ $inheritedFrom = null;
+
+ if ($inherited !== null) {
+ $inherited = $inherited->getValue();
+ }
+
+ if ($inherited === null) {
+ $inherited = $command->getResolvedVar($varName);
+ if ($inherited === null) {
+ $inheritedFrom = $command->getOriginForVar($varName);
+ }
+ } else {
+ $inheritedFrom = $command->getObjectName();
+ }
+
+ $inherited = $command->getResolvedVar($varName);
+
+ return [$inherited, $inheritedFrom];
+ } catch (\Exception $e) {
+ return null;
+ }
+ }
+}