From 3db53126786aebe283535ba07dbd595ff1b467e7 Mon Sep 17 00:00:00 2001 From: MEFRREEX Date: Thu, 18 Jan 2024 17:07:18 +0200 Subject: [PATCH] Added logic --- .gitignore | 220 ++++++++++++++++++ README.md | 114 +++++++++ plugin.yml | 14 ++ src/com/formconstructor/FormConstructor.php | 66 ++++++ src/com/formconstructor/event/FormEvent.php | 22 ++ .../event/PlayerFormCloseEvent.php | 20 ++ .../event/PlayerFormSendEvent.php | 30 +++ .../formconstructor/form/CloseableForm.php | 23 ++ src/com/formconstructor/form/CustomForm.php | 98 ++++++++ src/com/formconstructor/form/Form.php | 60 +++++ src/com/formconstructor/form/FormType.php | 13 ++ src/com/formconstructor/form/ModalForm.php | 92 ++++++++ src/com/formconstructor/form/SimpleForm.php | 93 ++++++++ .../form/element/ElementType.php | 16 ++ .../form/element/FormElement.php | 32 +++ .../form/element/SelectableElement.php | 35 +++ .../form/element/custom/CustomElement.php | 32 +++ .../form/element/custom/Dropdown.php | 81 +++++++ .../form/element/custom/Input.php | 101 ++++++++ .../form/element/custom/Label.php | 23 ++ .../form/element/custom/Slider.php | 93 ++++++++ .../form/element/custom/StepSlider.php | 86 +++++++ .../form/element/custom/Toggle.php | 47 ++++ .../element/custom/validator/IValidator.php | 14 ++ .../custom/validator/LengthValidator.php | 19 ++ .../custom/validator/RegexValidator.php | 17 ++ .../element/custom/validator/Validator.php | 27 +++ .../form/element/simple/Button.php | 43 ++++ .../form/element/simple/ButtonImage.php | 37 +++ .../form/element/simple/ImageType.php | 12 + .../form/response/CustomFormResponse.php | 136 +++++++++++ .../form/response/FormResponse.php | 27 +++ .../form/response/ModalFormResponse.php | 19 ++ .../form/response/SimpleFormResponse.php | 22 ++ .../formconstructor/task/FormHandlingTask.php | 52 +++++ 35 files changed, 1836 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 plugin.yml create mode 100644 src/com/formconstructor/FormConstructor.php create mode 100644 src/com/formconstructor/event/FormEvent.php create mode 100644 src/com/formconstructor/event/PlayerFormCloseEvent.php create mode 100644 src/com/formconstructor/event/PlayerFormSendEvent.php create mode 100644 src/com/formconstructor/form/CloseableForm.php create mode 100644 src/com/formconstructor/form/CustomForm.php create mode 100644 src/com/formconstructor/form/Form.php create mode 100644 src/com/formconstructor/form/FormType.php create mode 100644 src/com/formconstructor/form/ModalForm.php create mode 100644 src/com/formconstructor/form/SimpleForm.php create mode 100644 src/com/formconstructor/form/element/ElementType.php create mode 100644 src/com/formconstructor/form/element/FormElement.php create mode 100644 src/com/formconstructor/form/element/SelectableElement.php create mode 100644 src/com/formconstructor/form/element/custom/CustomElement.php create mode 100644 src/com/formconstructor/form/element/custom/Dropdown.php create mode 100644 src/com/formconstructor/form/element/custom/Input.php create mode 100644 src/com/formconstructor/form/element/custom/Label.php create mode 100644 src/com/formconstructor/form/element/custom/Slider.php create mode 100644 src/com/formconstructor/form/element/custom/StepSlider.php create mode 100644 src/com/formconstructor/form/element/custom/Toggle.php create mode 100644 src/com/formconstructor/form/element/custom/validator/IValidator.php create mode 100644 src/com/formconstructor/form/element/custom/validator/LengthValidator.php create mode 100644 src/com/formconstructor/form/element/custom/validator/RegexValidator.php create mode 100644 src/com/formconstructor/form/element/custom/validator/Validator.php create mode 100644 src/com/formconstructor/form/element/simple/Button.php create mode 100644 src/com/formconstructor/form/element/simple/ButtonImage.php create mode 100644 src/com/formconstructor/form/element/simple/ImageType.php create mode 100644 src/com/formconstructor/form/response/CustomFormResponse.php create mode 100644 src/com/formconstructor/form/response/FormResponse.php create mode 100644 src/com/formconstructor/form/response/ModalFormResponse.php create mode 100644 src/com/formconstructor/form/response/SimpleFormResponse.php create mode 100644 src/com/formconstructor/task/FormHandlingTask.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bb381ff --- /dev/null +++ b/.gitignore @@ -0,0 +1,220 @@ +.idea/ + +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +############# +## Windows detritus +############# + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist/ +build/ +eggs/ +parts/ +var/ +sdist/ +develop-eggs/ +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg + +/phpstan/vendor/ +/phpstan/composer.lock diff --git a/README.md b/README.md new file mode 100644 index 0000000..199f1ef --- /dev/null +++ b/README.md @@ -0,0 +1,114 @@ +🛠 Examples +------------- + +Creating a SimpleForm: + +```php +$form = new SimpleForm("Sample title"); +$form->addContent("New content line"); + +// Easiest way to add a button +$form->addButton(new Button("Button", function (Player $pl, Button $b) { + $pl->sendMessage("Button clicked: " . $b->getName() . " (" . $b->getIndex() . ")"); + })) + + // Button with image + ->addButton((new Button("Button with image")) + ->setImage(ImageType::PATH, "textures/items/diamond")) + + // Another way to add a button + ->addButton((new Button("Another button")) + ->setImage(ImageType::PATH, "textures/blocks/stone") + ->onClick(function (Player $pl, Button $b) { + $pl->sendMessage("Another button clicked: " . $b->getName() . " (" . $b->getIndex() . ")"); + })); + +// Setting the form close handler +$form->setCloseHandler(function (Player $pl) { + $pl->sendMessage("You closed the form!"); +}); + +$form->send($player); +``` + +Creating a ModalForm: + +```php +$form = new ModalForm("Test modal form"); +$form->addContent("New content line"); + +$form->setPositiveButton("Positive button") + ->setNegativeButton("Negative button"); + +// Setting the form handler +// Result returns true if a positive button was ckicked and false if a negative button was ckicked +$form->setHandler(function (Player $pl, bool $result) { + $pl->sendMessage("You clicked " . ($result ? "correct" : "wrong") . " button!"); +}); + +// Setting the form close handler +$form->setCloseHandler(fn(Player $pl) => $pl->sendMessage("You closed the form!")); + +$form->send($sender); +``` + +Creating a CustomForm: + +```php +$form = new CustomForm("Test custom form"); + +$form->addContent("Test label") + ->addElement("input", (new Input("Input")) + ->setPlaceholder("Text") + ->setDefaultValue("Default value")) + ->addElement("slider", new Slider("Slider", 1, 100, 1, 1)) + ->addElement("stepslider", (new StepSlider("Step slider")) + ->addText("1") + ->addText("2") + ->addText("3")) + ->addElement("dropdown", (new Dropdown("Dropdown")) + ->addText("Element 1") + ->addText("Element 2") + ->addText("Element 3")) + ->addElement("dropdown1", (new Dropdown("Second dropdown")) + ->addElement(new SelectableElement("Option 1")) + ->addElement(new SelectableElement("Option 2")) + ->addElement(new SelectableElement("Option with value", 15))) + ->addElement("toggle", new Toggle("Toggle", false)); + +// Setting the form handler +$form->setHandler(function (Player $pl, CustomFormResponse $response) { + $input = $response->getInput("input")->getValue(); + + $slider = $response->getSlider("slider")->getValue(); + $stepslider = $response->getStepSlider("stepslider")->getValue(); + $dropdown = $response->getDropdown("dropdown")->getValue(); + + // Getting the value we set in SelectableElement + $dropdownValue = $response->getDropdown("dropdown1")->getValue()->getValue(); + + $toggle = $response->getToggle("toggle")->getValue(); + + $pl->sendMessage("Input: " . $input . ", Slider: " . $slider . ", Step Slider: " . $stepslider . ", Dropdown: " . $dropdown . ", Toggle: " . $toggle); + $pl->sendMessage("Second dropdown value: " . $dropdownValue); +}); + +$form->send($sender); +``` + +📋 Events +------------- +| Name | Cancellable | Description | +|----------------------|-------------|----------------------------------| +| PlayerFormSendEvent | true | Called when a form is sent | +| PlayerFormCloseEvent | false | Called when the form is closed | + +Example: +```php +public function onFormSend(PlayerFormSendEvent $event) { + // Getting a player + $player = $event->getPlayer(); + // Getting the form + $form = $event->getForm(); +} +``` \ No newline at end of file diff --git a/plugin.yml b/plugin.yml new file mode 100644 index 0000000..5d2cee2 --- /dev/null +++ b/plugin.yml @@ -0,0 +1,14 @@ +name: FormConstructor +main: com\formconstructor\FormConstructor +version: 1.0.0 +api: 5.0.0 +author: MEFRREEX + +commands: + test: + description: "Test" + permission: "test.test" + +permissions: + test.test: + default: "op" \ No newline at end of file diff --git a/src/com/formconstructor/FormConstructor.php b/src/com/formconstructor/FormConstructor.php new file mode 100644 index 0000000..fabd044 --- /dev/null +++ b/src/com/formconstructor/FormConstructor.php @@ -0,0 +1,66 @@ +getName() === "test") { + $form = new SimpleForm("Sample title"); + $form->addContent("New content line"); + +// Easiest way to add a button + $form->addButton(new Button("Button", function (Player $pl, Button $b) { + $pl->sendMessage("Button clicked: " . $b->getName() . " (" . $b->getIndex() . ")"); + })) + + // Button with image + ->addButton((new Button("Button with image")) + ->setImage(ImageType::PATH, "textures/items/diamond")) + + // Another way to add a button + ->addButton((new Button("Another button")) + ->setImage(ImageType::PATH, "textures/blocks/stone") + ->onClick(function (Player $pl, Button $b) { + $pl->sendMessage("Another button clicked: " . $b->getName() . " (" . $b->getIndex() . ")"); + })); + +// Setting the form close handler + $form->setCloseHandler(function (Player $pl) { + $pl->sendMessage("You closed the form!"); + }); + + $form->send($sender); + } + return true; + } +} diff --git a/src/com/formconstructor/event/FormEvent.php b/src/com/formconstructor/event/FormEvent.php new file mode 100644 index 0000000..61f5bd2 --- /dev/null +++ b/src/com/formconstructor/event/FormEvent.php @@ -0,0 +1,22 @@ +form = $form; + } + + public function getForm(): Form { + return $this->form; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/event/PlayerFormCloseEvent.php b/src/com/formconstructor/event/PlayerFormCloseEvent.php new file mode 100644 index 0000000..4f9851f --- /dev/null +++ b/src/com/formconstructor/event/PlayerFormCloseEvent.php @@ -0,0 +1,20 @@ +player = $player; + } + + public function getPlayer(): Player { + return $this->player; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/event/PlayerFormSendEvent.php b/src/com/formconstructor/event/PlayerFormSendEvent.php new file mode 100644 index 0000000..e6ff021 --- /dev/null +++ b/src/com/formconstructor/event/PlayerFormSendEvent.php @@ -0,0 +1,30 @@ +player = $player; + $this->async = $async; + } + + public function getPlayer(): Player { + return $this->player; + } + + public function isAsync(): bool { + return $this->async; + } + + public function setAsync(bool $async): void { + $this->async = $async; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/CloseableForm.php b/src/com/formconstructor/form/CloseableForm.php new file mode 100644 index 0000000..4ba18f3 --- /dev/null +++ b/src/com/formconstructor/form/CloseableForm.php @@ -0,0 +1,23 @@ +closeHandler; + } + + public function setCloseHandler(Closure $closeHandler): self { + $this->closeHandler = $closeHandler; + return $this; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/CustomForm.php b/src/com/formconstructor/form/CustomForm.php new file mode 100644 index 0000000..3611ad0 --- /dev/null +++ b/src/com/formconstructor/form/CustomForm.php @@ -0,0 +1,98 @@ +title = $title; + $this->handler = $handler; + } + + public function getTitle(): string { + return $this->title; + } + + public function setTitle(string $title): self { + $this->title = $title; + return $this; + } + + public function addContent(string $addition): self { + return $this->addElement(null, new Label($addition)); + } + + public function addElement(?string $elementId, CustomElement $element): self { + $element->setElementId($elementId); + $this->elements[] = $element; + return $this; + } + + public function isValidated(): bool { + return $this->validated; + } + + public function setHandler(Closure $handler): self { + $this->handler = $handler; + return $this; + } + + public function getResponse(): ?FormResponse { + return $this->response; + } + + public function setResponse(mixed $data): void { + if ($data === null) { + return; + } + + foreach ($this->elements as $i => $element) { + if (!$element->respond($data[$i])) { + $this->response = new CustomFormResponse( + function (Player $player, CustomFormResponse $response) { + $this->send($player); + }, + $this->elements, + $this + ); + return; + } + + if ($element instanceof IValidator && $this->validated && !$element->isValidated()) { + $this->validated = false; + } + } + + foreach ($this->elements as $index => $element) { + $element->setIndex($index); + } + + $this->response = new CustomFormResponse($this->handler, $this->elements, $this); + } + + public function jsonSerialize() : array{ + return [ + "type" => $this->getType(), + "title" => $this->title, + "content" => $this->elements + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/Form.php b/src/com/formconstructor/form/Form.php new file mode 100644 index 0000000..4cf67b7 --- /dev/null +++ b/src/com/formconstructor/form/Form.php @@ -0,0 +1,60 @@ +type = $type; + } + + public function send(Player $player, bool $async = false): void { + $event = new PlayerFormSendEvent($player, $this, $async); + $event->call(); + + if (!$event->isCancelled()) { + $this->async = $event->isAsync(); + $player->sendForm($this); + } + } + + public function sendAsync(Player $player) { + $this->send($player, true); + } + + public function getType(): FormType { + return $this->type; + } + + public function isAsync(): bool { + return $this->async; + } + + public abstract function setResponse(mixed $data); + + public abstract function getResponse(): ?FormResponse; + + public final function handleResponse(Player $player, $data): void { + $this->setResponse($data); + + $handler = new FormHandlingTask($this->getResponse(), $this, $player); + + if ($this->async) { + // TODO async handling + $handler->onRun(); + } else { + $handler->onRun(); + } + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/FormType.php b/src/com/formconstructor/form/FormType.php new file mode 100644 index 0000000..537119e --- /dev/null +++ b/src/com/formconstructor/form/FormType.php @@ -0,0 +1,13 @@ +value; + } +} diff --git a/src/com/formconstructor/form/ModalForm.php b/src/com/formconstructor/form/ModalForm.php new file mode 100644 index 0000000..adf7795 --- /dev/null +++ b/src/com/formconstructor/form/ModalForm.php @@ -0,0 +1,92 @@ +title = $title; + $this->content = $content; + $this->handler = $handler; + } + + public function getTitle(): string { + return $this->title; + } + + public function setTitle(string $title): self { + $this->title = $title; + return $this; + } + + public function getContent(): string { + return $this->content; + } + + public function setContent(string $content): self { + $this->content = $content; + return $this; + } + + public function addContent(string $addition): self { + $this->content .= $addition; + return $this; + } + + public function getPositiveButton(): string { + return $this->positiveButton; + } + + public function setPositiveButton(string $positiveButton): self { + $this->positiveButton = $positiveButton; + return $this; + } + + public function getNegativeButton(): string { + return $this->negativeButton; + } + + public function setNegativeButton(string $negativeButton): self { + $this->negativeButton = $negativeButton; + return $this; + } + + public function setHandler(Closure $handler): self { + $this->handler = $handler; + return $this; + } + + public function getResponse(): ?FormResponse { + return $this->response; + } + + public function setResponse(mixed $data): void { + if ($data !== null && $this->handler !== null) { + $this->response = new ModalFormResponse($this->handler, $data); + } + } + + public function jsonSerialize(): array { + return [ + "type" => $this->getType(), + "title" => $this->title, + "content" => $this->content, + "button1" => $this->positiveButton, + "button2" => $this->negativeButton, + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/SimpleForm.php b/src/com/formconstructor/form/SimpleForm.php new file mode 100644 index 0000000..1f38d65 --- /dev/null +++ b/src/com/formconstructor/form/SimpleForm.php @@ -0,0 +1,93 @@ +title = $title; + $this->content = $content; + } + + public function getTitle(): string { + return $this->title; + } + + public function setTitle(string $title): self { + $this->title = $title; + return $this; + } + + public function getContent(): string { + return $this->content; + } + + public function setContent(string $content): self { + $this->content = $content; + return $this; + } + + public function addContent(string $addition): self { + $this->content .= $addition; + return $this; + } + + public function getButtons(): array { + return $this->buttons; + } + + public function setButtons(array $buttons): self { + $this->buttons = $buttons; + return $this; + } + + public function addButton(Button $button): self { + $this->buttons[] = $button; + return $this; + } + + public function getResponse(): ?SimpleFormResponse { + return $this->response; + } + + public function setResponse(mixed $data): void { + if ($data === null) { + return; + } + + if (!is_int($data)) { + return; + } + + if ($data < 0 || $data >= count($this->buttons)) { + $invalidButton = new Button("Invalid", fn($pl, $b) => $this->send($pl)); + $this->response = new SimpleFormResponse($invalidButton); + return; + } + + foreach ($this->buttons as $index => $button) { + $button->setIndex($index); + } + + $this->response = new SimpleFormResponse($this->buttons[$data]); + } + + public function jsonSerialize(): array { + return [ + "type" => $this->getType(), + "title" => $this->title, + "content" => $this->content, + "buttons" => $this->buttons + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/ElementType.php b/src/com/formconstructor/form/element/ElementType.php new file mode 100644 index 0000000..bd9f6c9 --- /dev/null +++ b/src/com/formconstructor/form/element/ElementType.php @@ -0,0 +1,16 @@ +value; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/FormElement.php b/src/com/formconstructor/form/element/FormElement.php new file mode 100644 index 0000000..35b571e --- /dev/null +++ b/src/com/formconstructor/form/element/FormElement.php @@ -0,0 +1,32 @@ +name = $name; + } + + public function getName(): string { + return $this->name; + } + + public function setName(string $name): self { + $this->name = $name; + return $this; + } + + public function getIndex(): int { + return $this->index; + } + + public function setIndex(int $index): void { + $this->index = $index; + } + + public abstract function jsonSerialize(): array; +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/SelectableElement.php b/src/com/formconstructor/form/element/SelectableElement.php new file mode 100644 index 0000000..3a9a906 --- /dev/null +++ b/src/com/formconstructor/form/element/SelectableElement.php @@ -0,0 +1,35 @@ +name = $name; + $this->value = $value; + } + + public function getName(): string { + return $this->name; + } + + public function getValue(): mixed { + return $this->value; + } + + public function getIndex(): int { + return $this->index; + } + + public function setIndex(int $index): void { + $this->index = $index; + } + + public function __toString(): string { + return "SelectableElement(name: " . $this->name . ", value: " . $this->value . ", index: " . $this->index . ")"; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/custom/CustomElement.php b/src/com/formconstructor/form/element/custom/CustomElement.php new file mode 100644 index 0000000..ad1d333 --- /dev/null +++ b/src/com/formconstructor/form/element/custom/CustomElement.php @@ -0,0 +1,32 @@ +type = $type; + + } + + public abstract function respond(mixed $data): bool; + + public function getType(): ElementType { + return $this->type; + } + + public function getElementId(): ?string { + return $this->elementId; + } + + public function setElementId(?string $elementId): void { + $this->elementId = $elementId; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/custom/Dropdown.php b/src/com/formconstructor/form/element/custom/Dropdown.php new file mode 100644 index 0000000..8c599f8 --- /dev/null +++ b/src/com/formconstructor/form/element/custom/Dropdown.php @@ -0,0 +1,81 @@ +addElements($elements); + $this->defaultIndex = $defaultIndex; + } + + public function addElement(SelectableElement $element): Dropdown { + $element->setIndex(count($this->elements)); + $this->elements[] = $element; + $this->options[] = $element->getName(); + return $this; + } + + public function addElements(array $elements): Dropdown { + foreach ($elements as $element) $this->addElement($element); + return $this; + } + + public function addText(string $name): Dropdown { + return $this->addElement(new SelectableElement($name, null)); + } + + public function setDefaultIndex(int $defaultIndex): Dropdown { + $this->defaultIndex = $defaultIndex; + return $this; + } + + public function getDefaultIndex(): int { + return $this->defaultIndex; + } + + public function getElements(): array { + return $this->elements; + } + + public function getSelectedIndex(): int { + return $this->selectedIndex; + } + + public function getDefault(): ?SelectableElement { + return empty($this->elements) ? null : $this->elements[$this->defaultIndex]; + } + + public function getValue(): ?SelectableElement { + return empty($this->elements) ? null : $this->elements[$this->selectedIndex]; + } + + public function respond(mixed $data): bool { + $this->selectedIndex = (int) $data; + return !empty($this->elements) && $this->selectedIndex >= 0 && $this->selectedIndex < count($this->elements); + } + + public function jsonSerialize() : array{ + return [ + "type" => $this->getType(), + "text" => $this->getName(), + "options" => $this->options, + "default" => $this->defaultIndex + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/custom/Input.php b/src/com/formconstructor/form/element/custom/Input.php new file mode 100644 index 0000000..f9be390 --- /dev/null +++ b/src/com/formconstructor/form/element/custom/Input.php @@ -0,0 +1,101 @@ +placeholder = $placeholder; + $this->defaultValue = $defaultValue; + } + + public function getPlaceholder(): string { + return $this->placeholder; + } + + public function setPlaceholder(string $placeholder): self { + $this->placeholder = $placeholder; + return $this; + } + + public function getDefaultValue(): string { + return $this->defaultValue; + } + + public function setDefaultValue(string $defaultValue): self { + $this->defaultValue = $defaultValue; + return $this; + } + + public function getValue(): string { + return $this->value; + } + + public function setValue(string $value): self { + $this->value = $value; + return $this; + } + + public function isTrim(): bool { + return $this->trim; + } + + public function setTrim(bool $trim): self { + $this->trim = $trim; + return $this; + } + + public function validate(): void { + foreach ($this->validators as $validator) { + $validator->validate($this->value); + } + } + + public function isValidated(): bool { + return array_reduce( + $this->validators, + fn($carry, $validator) => $carry && $validator->isValidated(), + true + ); + } + + public function getValidators(): array { + return $this->validators; + } + + public function addValidator(Validator $validator): self { + $this->validators[] = $validator; + return $this; + } + + public function respond(mixed $data): bool { + $this->value = $this->trim ? trim($data) : $data; + $this->validate(); + return true; + } + + public function jsonSerialize() : array { + return [ + "type" => $this->getType(), + "text" => $this->getName(), + "placeholder" => $this->placeholder, + "default" => $this->defaultValue + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/custom/Label.php b/src/com/formconstructor/form/element/custom/Label.php new file mode 100644 index 0000000..7823326 --- /dev/null +++ b/src/com/formconstructor/form/element/custom/Label.php @@ -0,0 +1,23 @@ + $this->getType(), + "text" => $this->getName() + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/custom/Slider.php b/src/com/formconstructor/form/element/custom/Slider.php new file mode 100644 index 0000000..f729d7a --- /dev/null +++ b/src/com/formconstructor/form/element/custom/Slider.php @@ -0,0 +1,93 @@ +min = max($min, 0.0); + $this->max = max($max, $this->min); + $this->defaultValue = $defaultValue; + if ($step > 0) { + $this->step = $step; + } + } + + public function getDefaultValue(): float { + return $this->defaultValue; + } + + public function setDefaultValue(float $defaultValue): self { + $this->defaultValue = $defaultValue; + return $this; + } + + public function getMin(): float { + return $this->min; + } + + public function setMin(float $min): self { + $this->min = $min; + return $this; + } + + public function getMax(): float { + return $this->max; + } + + public function setMax(float $max): self { + $this->max = $max; + return $this; + } + + public function getStep(): float { + return $this->step; + } + + public function setStep(float $step): self { + $this->step = $step; + return $this; + } + + public function getValue(): int { + return $this->value; + } + + public function setValue(float $value): self { + $this->value = $value; + return $this; + } + + public function respond(mixed $data): bool { + $this->value = (float) $data; + return $this->value >= $this->min && $this->value <= $this->max; + } + + public function jsonSerialize() : array{ + return [ + "type" => $this->getType(), + "text" => $this->getName(), + "min" => $this->min, + "max" => $this->max, + "step" => $this->step, + "default" => $this->defaultValue + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/custom/StepSlider.php b/src/com/formconstructor/form/element/custom/StepSlider.php new file mode 100644 index 0000000..d26b074 --- /dev/null +++ b/src/com/formconstructor/form/element/custom/StepSlider.php @@ -0,0 +1,86 @@ +addSteps($elements); + $this->defaultIndex = $defaultIndex; + } + + public function addStep(SelectableElement $element): self { + $element->setIndex(count($this->elements)); + $this->elements[] = $element; + $this->options[] = $element->getName(); + return $this; + } + + public function addSteps(array $elements): self { + foreach ($elements as $element) $this->addStep($element); + return $this; + } + + public function addText(string $name): self { + return $this->addStep(new SelectableElement($name, null)); + } + + public function setDefaultIndex(int $defaultIndex): self { + $this->defaultIndex = $defaultIndex; + return $this; + } + + public function getDefaultIndex(): int { + return $this->defaultIndex; + } + + public function getElements(): array { + return $this->elements; + } + + public function getSelectedIndex(): int { + return $this->selectedIndex; + } + + public function getDefault(): ?SelectableElement { + return empty($this->elements) ? null : $this->elements[$this->defaultIndex]; + } + + public function getValue(): ?SelectableElement { + return empty($this->elements) ? null : $this->elements[$this->selectedIndex]; + } + + public function respond(mixed $data): bool { + $this->selectedIndex = (int) $data; + + if (empty($this->elements) || $this->selectedIndex < 0 || (count($this->elements) == 1 && $this->selectedIndex == 1)) { + return true; + } + + return $this->selectedIndex < count($this->elements); + } + + public function jsonSerialize() : array{ + return [ + "type" => $this->getType(), + "text" => $this->getName(), + "steps" => $this->options, + "default" => $this->defaultIndex + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/custom/Toggle.php b/src/com/formconstructor/form/element/custom/Toggle.php new file mode 100644 index 0000000..2d4cdd5 --- /dev/null +++ b/src/com/formconstructor/form/element/custom/Toggle.php @@ -0,0 +1,47 @@ +defaultValue = $defaultValue; + } + + public function getValue(): bool { + return $this->value; + } + + public function getDefaultValue(): bool { + return $this->defaultValue; + } + + public function setDefaultValue(bool $defaultValue): self { + $this->defaultValue = $defaultValue; + return $this; + } + + public function respond(mixed $data): bool { + if (!is_bool($data)) { + throw new FormValidationException(); + } + $this->value = $data; + return true; + } + + public function jsonSerialize(): array { + return [ + "type" => $this->getType(), + "text" => $this->getName(), + "default" => $this->defaultValue + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/custom/validator/IValidator.php b/src/com/formconstructor/form/element/custom/validator/IValidator.php new file mode 100644 index 0000000..6af811c --- /dev/null +++ b/src/com/formconstructor/form/element/custom/validator/IValidator.php @@ -0,0 +1,14 @@ +min = $min; + $this->max = $max; + } + + public function validate(string $input): void { + $this->setValidated(($this->min === -1 || strlen($input) >= $this->min) && ($this->max === -1 || $this->max >= strlen($input))); + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/custom/validator/RegexValidator.php b/src/com/formconstructor/form/element/custom/validator/RegexValidator.php new file mode 100644 index 0000000..45ff3f3 --- /dev/null +++ b/src/com/formconstructor/form/element/custom/validator/RegexValidator.php @@ -0,0 +1,17 @@ +regex = $regex; + } + + public function validate(string $input): void { + $this->setValidated(preg_match($this->regex, $input) === 1); + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/custom/validator/Validator.php b/src/com/formconstructor/form/element/custom/validator/Validator.php new file mode 100644 index 0000000..8a3e775 --- /dev/null +++ b/src/com/formconstructor/form/element/custom/validator/Validator.php @@ -0,0 +1,27 @@ +name = $name; + } + + public function getName(): string { + return $this->name; + } + + public function isValidated(): bool { + return $this->validated; + } + + protected function setValidated(bool $validated): void { + $this->validated = $validated; + } + + public abstract function validate(string $input); +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/simple/Button.php b/src/com/formconstructor/form/element/simple/Button.php new file mode 100644 index 0000000..52e0440 --- /dev/null +++ b/src/com/formconstructor/form/element/simple/Button.php @@ -0,0 +1,43 @@ +handler = $handler; + $this->image = new ButtonImage(); + } + + public function getImage(): ButtonImage { + return $this->image; + } + + public function setImage(ImageType $imageType, string $image): self { + $this->image = new ButtonImage($imageType, $image); + return $this; + } + + public function getHandler(): ?Closure { + return $this->handler; + } + + public function onClick(callable $handler): self { + $this->handler = $handler; + return $this; + } + + public function jsonSerialize(): array { + return [ + "text" => $this->getName(), + "image" => $this->image + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/simple/ButtonImage.php b/src/com/formconstructor/form/element/simple/ButtonImage.php new file mode 100644 index 0000000..392dfb5 --- /dev/null +++ b/src/com/formconstructor/form/element/simple/ButtonImage.php @@ -0,0 +1,37 @@ +type = $type; + $this->path = $path; + } + + public function getType(): ImageType { + return $this->type; + } + + public function setType(ImageType $type): void { + $this->type = $type; + } + + public function getPath(): string { + return $this->path; + } + + public function setPath(string $path): void { + $this->path = $path; + } + + public function jsonSerialize(): array { + return [ + "type" => $this->type, + "data" => $this->path, + ]; + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/element/simple/ImageType.php b/src/com/formconstructor/form/element/simple/ImageType.php new file mode 100644 index 0000000..16771ef --- /dev/null +++ b/src/com/formconstructor/form/element/simple/ImageType.php @@ -0,0 +1,12 @@ +value; + } +} diff --git a/src/com/formconstructor/form/response/CustomFormResponse.php b/src/com/formconstructor/form/response/CustomFormResponse.php new file mode 100644 index 0000000..7fffff2 --- /dev/null +++ b/src/com/formconstructor/form/response/CustomFormResponse.php @@ -0,0 +1,136 @@ +elements = $elements; + $this->form = $form; + } + + public function getAllElements(): array { + return $this->elements; + } + + public function getForm(): CustomForm { + return $this->form; + } + + public function containsId(string $elementId): bool { + foreach ($this->elements as $element) { + if ($element->getElementId() === $elementId) { + return true; + } + } + return false; + } + + private function getElementByIndex(int $index): ?CustomElement { + return $this->elements[$index]; + } + + private function getElement(string $elementId, ElementType $type): mixed { + foreach ($this->elements as $element) { + if ($element->getElementId() === $elementId && $element->getType() === $type) { + return $element; + } + } + return null; + } + + private function getElements(ElementType $type): array { + return array_filter($this->elements, fn(CustomElement $element) => $element->getType() === $type); + } + + public function getLabel(string $elementId): ?Label { + return $this->getElement($elementId, ElementType::LABEL); + } + + public function getLabels(): array { + return $this->getElements(ElementType::LABEL); + } + + public function getInput(string $elementId): ?Input { + return $this->getElement($elementId, ElementType::INPUT); + } + + public function getInputs(): array { + return $this->getElements(ElementType::INPUT); + } + + public function getToggle(string $elementId): ?Toggle { + return $this->getElement($elementId, ElementType::TOGGLE); + } + + public function getToggles(): array { + return $this->getElements(ElementType::TOGGLE); + } + + public function getSlider(string $elementId): ?Slider { + return $this->getElement($elementId, ElementType::SLIDER); + } + + public function getSliders(): array { + return $this->getElements(ElementType::SLIDER); + } + + public function getStepSlider(string $elementId): ?StepSlider { + return $this->getElement($elementId, ElementType::STEP_SLIDER); + } + + public function getStepSliders(): array { + return $this->getElements(ElementType::STEP_SLIDER); + } + + public function getDropdown(string $elementId): ?Dropdown { + return $this->getElement($elementId, ElementType::DROPDOWN); + } + + public function getDropdowns(): array { + return $this->getElements(ElementType::DROPDOWN); + } + + public function isValidated(): bool { + return $this->form->isValidated(); + } + + public function getValidatorErrors(): array { + $errors = []; + + foreach ($this->elements as $element) { + if ($element instanceof IValidator) { + foreach ($element->getValidators() as $validator) { + if (!$validator->isValidated()) { + $errors[] = $validator->getName(); + } + } + } + } + + return $errors; + } + + public function handle(Player $player): void { + if ($this->getHandler() !== null) { + $this->getHandler()($player, $this); + } + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/response/FormResponse.php b/src/com/formconstructor/form/response/FormResponse.php new file mode 100644 index 0000000..0a6fa00 --- /dev/null +++ b/src/com/formconstructor/form/response/FormResponse.php @@ -0,0 +1,27 @@ +handler = $handler; + $this->data = $data; + } + + public function getHandler(): ?Closure { + return $this->handler; + } + + public function getData(): ?string { + return $this->data; + } + + public abstract function handle(Player $player): void; +} \ No newline at end of file diff --git a/src/com/formconstructor/form/response/ModalFormResponse.php b/src/com/formconstructor/form/response/ModalFormResponse.php new file mode 100644 index 0000000..c44663f --- /dev/null +++ b/src/com/formconstructor/form/response/ModalFormResponse.php @@ -0,0 +1,19 @@ +getHandler() !== null) { + $this->getHandler()($player, $this->getData() === "1"); + } + } +} \ No newline at end of file diff --git a/src/com/formconstructor/form/response/SimpleFormResponse.php b/src/com/formconstructor/form/response/SimpleFormResponse.php new file mode 100644 index 0000000..83de674 --- /dev/null +++ b/src/com/formconstructor/form/response/SimpleFormResponse.php @@ -0,0 +1,22 @@ +getHandler(), ""); + $this->button = $button; + } + + public function handle(Player $player): void { + if ($this->getHandler() !== null) { + $this->getHandler()($player, $this->button); + } + } +} \ No newline at end of file diff --git a/src/com/formconstructor/task/FormHandlingTask.php b/src/com/formconstructor/task/FormHandlingTask.php new file mode 100644 index 0000000..474709e --- /dev/null +++ b/src/com/formconstructor/task/FormHandlingTask.php @@ -0,0 +1,52 @@ +response = $response; + $this->form = $form; + $this->player = $player; + } + + public function onRun(): void { + if ($this->response === null && $this->form instanceof CloseableForm) { + $closeHandler = $this->form->getCloseHandler(); + + $event = new PlayerFormCloseEvent($this->player, $this->form); + $event->call(); + + if ($closeHandler !== null) $closeHandler($this->player); + return; + } + + if ($this->response instanceof ModalFormResponse) { + $this->response->handle($this->player); + return; + } + + if ($this->response instanceof SimpleFormResponse) { + $this->response->handle($this->player); + return; + } + + if ($this->response instanceof CustomFormResponse) { + $this->response->handle($this->player); + } + } +} \ No newline at end of file