123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- <?php
- /**
- * @package Grav\Framework\Flex
- *
- * @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
- * @license MIT License; see LICENSE file for details.
- */
- namespace Grav\Framework\Flex;
- use Grav\Common\Data\Blueprint;
- use Grav\Common\Data\Data;
- use Grav\Common\Grav;
- use Grav\Common\Twig\Twig;
- use Grav\Common\Utils;
- use Grav\Framework\Flex\Interfaces\FlexFormInterface;
- use Grav\Framework\Flex\Interfaces\FlexObjectInterface;
- use Grav\Framework\Form\Traits\FormTrait;
- use Grav\Framework\Route\Route;
- use Twig\Error\LoaderError;
- use Twig\Error\SyntaxError;
- use Twig\Template;
- use Twig\TemplateWrapper;
- /**
- * Class FlexForm
- * @package Grav\Framework\Flex
- */
- class FlexForm implements FlexFormInterface
- {
- use FormTrait {
- FormTrait::doSerialize as doTraitSerialize;
- FormTrait::doUnserialize as doTraitUnserialize;
- }
- /** @var array|null */
- private $form;
- /** @var FlexObjectInterface */
- private $object;
- /**
- * FlexForm constructor.
- * @param string $name
- * @param FlexObjectInterface $object
- * @param array|null $form
- */
- public function __construct(string $name, FlexObjectInterface $object, array $form = null)
- {
- $this->name = $name;
- $this->form = $form;
- $uniqueId = $object->exists() ? $object->getStorageKey() : "{$object->getFlexType()}:new";
- $this->setObject($object);
- $this->setId($this->getName());
- $this->setUniqueId(md5($uniqueId));
- $this->messages = [];
- $this->submitted = false;
- $flash = $this->getFlash();
- if ($flash->exists()) {
- $data = $flash->getData();
- $includeOriginal = (bool)($this->getBlueprint()->form()['images']['original'] ?? null);
- $this->data = $data ? new Data($data, $this->getBlueprint()) : null;
- $this->files = $flash->getFilesByFields($includeOriginal);
- } else {
- $this->data = null;
- $this->files = [];
- }
- }
- /**
- * @return string
- */
- public function getName(): string
- {
- $object = $this->getObject();
- $name = $this->name ?: 'object';
- return "flex-{$object->getFlexType()}-{$name}";
- }
- /**
- * @return Data|FlexObjectInterface|object
- */
- public function getData()
- {
- return $this->data ?? $this->getObject();
- }
- /**
- * Get a value from the form.
- *
- * Note: Used in form fields.
- *
- * @param string $name
- * @return mixed
- */
- public function getValue(string $name)
- {
- // Attempt to get value from the form data.
- $value = $this->data ? $this->data[$name] : null;
- // Return the form data or fall back to the object property.
- return $value ?? $this->getObject()->getFormValue($name);
- }
- public function getDefaultValue(string $name)
- {
- return $this->object->getDefaultValue($name);
- }
- /**
- * @return array
- */
- public function getDefaultValues(): array
- {
- return $this->object->getDefaultValues();
- }
- /**
- * @return string
- */
- public function getFlexType(): string
- {
- return $this->object->getFlexType();
- }
- /**
- * @return FlexObjectInterface
- */
- public function getObject(): FlexObjectInterface
- {
- return $this->object;
- }
- public function updateObject(): FlexObjectInterface
- {
- $data = $this->data instanceof Data ? $this->data->toArray() : [];
- $files = $this->files;
- return $this->getObject()->update($data, $files);
- }
- /**
- * @return Blueprint
- */
- public function getBlueprint(): Blueprint
- {
- if (null === $this->blueprint) {
- try {
- $blueprint = $this->getObject()->getBlueprint(Utils::isAdminPlugin() ? '' : $this->name);
- if ($this->form) {
- // We have field overrides available.
- $blueprint->extend(['form' => $this->form], true);
- $blueprint->init();
- }
- } catch (\RuntimeException $e) {
- if (!isset($this->form['fields'])) {
- throw $e;
- }
- // Blueprint is not defined, but we have custom form fields available.
- $blueprint = new Blueprint(null, ['form' => $this->form]);
- $blueprint->load();
- $blueprint->setScope('object');
- $blueprint->init();
- }
- $this->blueprint = $blueprint;
- }
- return $this->blueprint;
- }
- /**
- * @return Route|null
- */
- public function getFileUploadAjaxRoute(): ?Route
- {
- $object = $this->getObject();
- if (!method_exists($object, 'route')) {
- return null;
- }
- return $object->route('/edit.json/task:media.upload');
- }
- /**
- * @param string $field
- * @param string $filename
- * @return Route|null
- */
- public function getFileDeleteAjaxRoute($field, $filename): ?Route
- {
- $object = $this->getObject();
- if (!method_exists($object, 'route')) {
- return null;
- }
- return $object->route('/edit.json/task:media.delete');
- }
- public function getMediaTaskRoute(array $params = [], $extension = null): string
- {
- $grav = Grav::instance();
- /** @var Flex $flex */
- $flex = $grav['flex_objects'];
- if (method_exists($flex, 'adminRoute')) {
- return $flex->adminRoute($this->getObject(), $params, $extension ?? 'json');
- }
- return '';
- }
- /**
- * Implements \Serializable::unserialize().
- *
- * @param string $data
- */
- public function unserialize($data): void
- {
- $data = unserialize($data, ['allowed_classes' => [FlexObject::class]]);
- $this->doUnserialize($data);
- }
- public function __get($name)
- {
- $method = "get{$name}";
- if (method_exists($this, $method)) {
- return $this->{$method}();
- }
- $form = $this->getBlueprint()->form();
- return $form[$name] ?? null;
- }
- public function __set($name, $value)
- {
- $method = "set{$name}";
- if (method_exists($this, $method)) {
- $this->{$method}($value);
- }
- }
- public function __isset($name)
- {
- $method = "get{$name}";
- if (method_exists($this, $method)) {
- return true;
- }
- $form = $this->getBlueprint()->form();
- return isset($form[$name]);
- }
- public function __unset($name)
- {
- }
- /**
- * Note: this method clones the object.
- *
- * @param FlexObjectInterface $object
- * @return $this
- */
- protected function setObject(FlexObjectInterface $object): self
- {
- $this->object = clone $object;
- return $this;
- }
- /**
- * @param string $layout
- * @return Template|TemplateWrapper
- * @throws LoaderError
- * @throws SyntaxError
- */
- protected function getTemplate($layout)
- {
- $grav = Grav::instance();
- /** @var Twig $twig */
- $twig = $grav['twig'];
- return $twig->twig()->resolveTemplate(
- [
- "flex-objects/layouts/{$this->getFlexType()}/form/{$layout}.html.twig",
- "flex-objects/layouts/_default/form/{$layout}.html.twig",
- "forms/{$layout}/form.html.twig",
- 'forms/default/form.html.twig'
- ]
- );
- }
- /**
- * @param array $data
- * @param array $files
- * @throws \Exception
- */
- protected function doSubmit(array $data, array $files)
- {
- /** @var FlexObject $object */
- $object = clone $this->getObject();
- $object->update($data, $files);
- $object->save();
- $this->setObject($object);
- $this->reset();
- }
- protected function doSerialize(): array
- {
- return $this->doTraitSerialize() + [
- 'object' => $this->object,
- ];
- }
- protected function doUnserialize(array $data): void
- {
- $this->doTraitUnserialize($data);
- $this->object = $data['object'];
- }
- /**
- * Filter validated data.
- *
- * @param \ArrayAccess $data
- */
- protected function filterData(\ArrayAccess $data): void
- {
- if ($data instanceof Data) {
- $data->filter(true, true);
- }
- }
- }
|