diff --git a/library/Icinga/Data/SimpleSuggestions.php b/library/Icinga/Data/SimpleSuggestions.php new file mode 100644 index 0000000000..111a950982 --- /dev/null +++ b/library/Icinga/Data/SimpleSuggestions.php @@ -0,0 +1,186 @@ +searchTerm = $searchTerm; + + return $this; + } + + /** Set the fetched data + * + * @param $data \Generator + * + * @return $this + */ + public function setData($data) + { + $this->data = $data; + + return $this; + } + + /** Set the default suggestion + * + * @param $default string + * + * @return $this + */ + public function setDefault($default) + { + $this->default = $default; + + return $this; + } + + /** The given input for search + * + * @param $searchTerm string + * + * @param $exclude array Already added terms to exclude in suggestion list + * + * @return mixed + */ + abstract protected function fetchSuggestions($searchTerm, $exclude); + + protected function assembleDefault() + { + if ($this->default === null) { + return; + } + + $attributes = [ + 'type' => 'button', + 'tabindex' => -1, + 'data-label' => $this->default, + 'data-type' => 'value', + 'value' => $this->default, + 'class' => 'value' + ]; + + $button = new ButtonElement(null, $attributes); + $button->addHtml(FormattedString::create( + t('Add %s'), + new HtmlElement('em', null, Text::create($this->default)) + )); + + + $this->prependHtml(new HtmlElement('li', Attributes::create(['class' => 'default']), $button)); + } + + protected function assemble() + { + if ($this->data === null) { + $data = []; + } else { + $data = $this->data; + } + + foreach ($data as $term => $meta) { + if (is_int($term)) { + $term = $meta; + } + + $attributes = [ + 'type' => 'button', + 'tabindex' => -1, + 'data-search' => $term + ]; + + $attributes['value'] = $meta; + $attributes['data-label'] = $meta; + + $this->addHtml(new HtmlElement('li', null, new InputElement(null, $attributes))); + } + + $showDefault = true; + if ($this->searchTerm && $this->count()) { + // The default option is not shown if the user's input result in an exact match + $input = $this->getFirst('li')->getFirst('input'); + $showDefault = $input->getValue() != $this->searchTerm + && $input->getAttributes()->get('data-search')->getValue() != $this->searchTerm; + } + + if ($showDefault) { + $this->assembleDefault(); + } + } + + /** + * Load suggestions as requested by the client + * + * @param ServerRequestInterface $request + * + * @return $this + */ + public function forRequest(ServerRequestInterface $request) + { + if ($request->getMethod() !== 'POST') { + return $this; + } + + $requestData = json_decode($request->getBody()->read(8192), true); + if (empty($requestData)) { + return $this; + } + + $search = $requestData['term']['search']; + $label = $requestData['term']['label']; + $exclude = $requestData['exclude']; + + $this->setSearchTerm($search); + + $this->setData($this->fetchSuggestions($label, $exclude)); + + if ($search) { + $this->setDefault($search); + } + + return $this; + } + + public function renderUnwrapped() + { + $this->ensureAssembled(); + + if ($this->isEmpty()) { + return ''; + } + + return parent::renderUnwrapped(); + } +}