false, self::OPTIONS_ELEMENT => false, self::OPTIONS_CONTENT => false, self::OPTIONS_LABEL => false, ]; private $element_id = 0; private function canContainData(array $element) { $non_data_elements = [ [ self::OPTIONS_ELEMENT => "button" ], [ self::OPTIONS_ELEMENT => "input", self::OPTIONS_TYPE => "submit", ], ]; foreach ($non_data_elements as $non) { if (count(array_intersect($non, $element)) == count($non)) { return false; } } return true; } private function generateFormElementName(bool $increase_element_id): string { return implode( '-', [ $this->getModuleName(), $this->getExecutionCount(), ($increase_element_id) ? $this->element_id++ : $this->element_id, ] ); } private function createFormElementGroup(array $element) { if (!isset($element[self::OPTIONS_LABEL])) { return $this->createFormElement($element); } else { $label = $this->createLabel($element); } $wrapper = $this->createAndSetupElement( 'div', '', [ 'class' => 'element-container' ] ); $wrapper->appendChild($label); $form_element = $this->createFormElement($element); $wrapper->appendChild($form_element); return $wrapper; } private function createFormElement(array $element) { $element += [self::OPTIONS_CONTENT => '']; if ($this->canContainData($element)) { // if no label given, the element id should be increased $element["name"] = $this->generateFormElementName( true//!array_key_exists($element[self::OPTIONS_LABEL]) ); $element["id"] = $element["name"]; } else { unset($element["name"]); } $form_element = $this->createAndSetupElement( $element[self::OPTIONS_ELEMENT], $element[self::OPTIONS_CONTENT], array_diff_key($element, $this->non_attribute_options) ); foreach ($element[self::OPTIONS_ELEMENTS] as $element) { $form_element->appendChild($this->createFormElementGroup($element)); } return $form_element; } private function createLabel(array $element) { $label = $this->createAndSetupElement( 'label', $element[self::OPTIONS_LABEL], [ 'for' => $this->generateFormElementName(false), ] ); return $label; } private function setupForm(array $elements) { foreach ($elements as $element) { $this->appendChild($this->createFormElementGroup($element)); } } private function collectFormKeys() { return preg_grep( '/' . $this->getModuleName() . '-' . $this->getExecutionCount() . '-\d+' . '/', array_keys($_POST) ); } /** * \brief IMPORTANT: Needs to be called AFTER setupForm to work correctly! */ private function isSubmitted() { return count($this->collectFormKeys()) > 0; } public function getData() { if (!$this->isSubmitted()) { return []; } $data = []; $keys = $this->collectFormKeys(); sort($keys, SORT_NUMERIC); foreach ($keys as $key) { $data [] = $_POST[$key]; } return $data; } private function processAction($action) { if ($action === '/') { return '/' . $this->getLanguage(); } if (strpos($action, '/') === 0) { return '/' . $this->getLanguage() . $action; } return implode('/', [ '', $this->getLanguage(), ($action ?? Resolve::idToUri($this->getPageId())), ]); } public function run(array $options = []) : bool { // SETUP FORM ATTRIBUTES $this->setAttribute('method', $options[self::OPTIONS_METHOD] ?? 'POST'); $this->setAttribute( 'action', $this->processAction($options[self::OPTIONS_ACTION]) ?? '/' ); $this->setupForm($options[self::OPTIONS_ELEMENTS]); if ($this->isSubmitted()) { return false; } return true; } public function onWebsocketRequest( \Lewp\Websocket\Message $message ) : \Lewp\Websocket\Message { } };