454 lines
10 KiB
PHP
454 lines
10 KiB
PHP
<?php
|
|
/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
|
|
|
|
namespace Icinga\Forms;
|
|
|
|
use Exception;
|
|
use Icinga\Data\Filter\Filter;
|
|
use Icinga\Exception\NotFoundError;
|
|
use Icinga\Repository\Repository;
|
|
use Icinga\Web\Form;
|
|
use Icinga\Web\Notification;
|
|
|
|
/**
|
|
* Form base-class providing standard functionality for extensible, updatable and reducible repositories
|
|
*/
|
|
abstract class RepositoryForm extends Form
|
|
{
|
|
/**
|
|
* Insert mode
|
|
*/
|
|
const MODE_INSERT = 0;
|
|
|
|
/**
|
|
* Update mode
|
|
*/
|
|
const MODE_UPDATE = 1;
|
|
|
|
/**
|
|
* Delete mode
|
|
*/
|
|
const MODE_DELETE = 2;
|
|
|
|
/**
|
|
* The repository being worked with
|
|
*
|
|
* @var Repository
|
|
*/
|
|
protected $repository;
|
|
|
|
/**
|
|
* The target being worked with
|
|
*
|
|
* @var mixed
|
|
*/
|
|
protected $baseTable;
|
|
|
|
/**
|
|
* How to interact with the repository
|
|
*
|
|
* @var int
|
|
*/
|
|
protected $mode;
|
|
|
|
/**
|
|
* The name of the entry being handled when in mode update or delete
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $identifier;
|
|
|
|
/**
|
|
* The data of the entry to pre-populate the form with when in mode insert or update
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $data;
|
|
|
|
/**
|
|
* Set the repository to work with
|
|
*
|
|
* @param Repository $repository
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function setRepository(Repository $repository)
|
|
{
|
|
$this->repository = $repository;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Return the target being worked with
|
|
*
|
|
* @return mixed
|
|
*/
|
|
protected function getBaseTable()
|
|
{
|
|
if ($this->baseTable === null) {
|
|
return $this->repository->getBaseTable();
|
|
}
|
|
|
|
return $this->baseTable;
|
|
}
|
|
|
|
/**
|
|
* Return the name of the entry to handle
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function getIdentifier()
|
|
{
|
|
return $this->identifier;
|
|
}
|
|
|
|
/**
|
|
* Return the current data of the entry being handled
|
|
*
|
|
* @return array
|
|
*/
|
|
protected function getData()
|
|
{
|
|
return $this->data;
|
|
}
|
|
|
|
/**
|
|
* Return whether an entry should be inserted
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function shouldInsert()
|
|
{
|
|
return $this->mode === self::MODE_INSERT;
|
|
}
|
|
|
|
/**
|
|
* Return whether an entry should be udpated
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function shouldUpdate()
|
|
{
|
|
return $this->mode === self::MODE_UPDATE;
|
|
}
|
|
|
|
/**
|
|
* Return whether an entry should be deleted
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function shouldDelete()
|
|
{
|
|
return $this->mode === self::MODE_DELETE;
|
|
}
|
|
|
|
/**
|
|
* Add a new entry
|
|
*
|
|
* @param array $data The defaults to use, if any
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function add(array $data = null)
|
|
{
|
|
$this->mode = static::MODE_INSERT;
|
|
$this->data = $data;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Edit an entry
|
|
*
|
|
* @param string $name The entry's name
|
|
* @param array $data The entry's current data
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function edit($name, array $data = null)
|
|
{
|
|
$this->mode = static::MODE_UPDATE;
|
|
$this->identifier = $name;
|
|
$this->data = $data;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Remove an entry
|
|
*
|
|
* @param string $name The entry's name
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function remove($name)
|
|
{
|
|
$this->mode = static::MODE_DELETE;
|
|
$this->identifier = $name;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Fetch and return the entry to pre-populate the form with when in mode update
|
|
*
|
|
* @return false|object
|
|
*/
|
|
protected function fetchEntry()
|
|
{
|
|
return $this->repository
|
|
->select()
|
|
->from($this->getBaseTable())
|
|
->applyFilter($this->createFilter())
|
|
->fetchRow();
|
|
}
|
|
|
|
/**
|
|
* Return whether the entry supposed to be removed exists
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function entryExists()
|
|
{
|
|
$count = $this->repository
|
|
->select()
|
|
->from($this->getBaseTable())
|
|
->addFilter($this->createFilter())
|
|
->count();
|
|
return $count > 0;
|
|
}
|
|
|
|
/**
|
|
* Insert the new entry
|
|
*/
|
|
protected function insertEntry()
|
|
{
|
|
$this->repository->insert($this->getBaseTable(), $this->getValues());
|
|
}
|
|
|
|
/**
|
|
* Update the entry
|
|
*/
|
|
protected function updateEntry()
|
|
{
|
|
$this->repository->update($this->getBaseTable(), $this->getValues(), $this->createFilter());
|
|
}
|
|
|
|
/**
|
|
* Delete the entry
|
|
*/
|
|
protected function deleteEntry()
|
|
{
|
|
$this->repository->delete($this->getBaseTable(), $this->createFilter());
|
|
}
|
|
|
|
/**
|
|
* Create and add elements to this form
|
|
*
|
|
* @param array $formData The data sent by the user
|
|
*/
|
|
public function createElements(array $formData)
|
|
{
|
|
if ($this->shouldInsert()) {
|
|
$this->createInsertElements($formData);
|
|
} elseif ($this->shouldUpdate()) {
|
|
$this->createUpdateElements($formData);
|
|
} elseif ($this->shouldDelete()) {
|
|
$this->createDeleteElements($formData);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prepare the form for the requested mode
|
|
*/
|
|
public function onRequest()
|
|
{
|
|
if ($this->shouldInsert()) {
|
|
$this->onInsertRequest();
|
|
} elseif ($this->shouldUpdate()) {
|
|
$this->onUpdateRequest();
|
|
} elseif ($this->shouldDelete()) {
|
|
$this->onDeleteRequest();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prepare the form for mode insert
|
|
*
|
|
* Populates the form with the data passed to add().
|
|
*/
|
|
protected function onInsertRequest()
|
|
{
|
|
$data = $this->getData();
|
|
if (! empty($data)) {
|
|
$this->setDefaults($data);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prepare the form for mode update
|
|
*
|
|
* Populates the form with either the data passed to edit() or tries to fetch it from the repository.
|
|
*
|
|
* @throws NotFoundError In case the entry to update cannot be found
|
|
*/
|
|
protected function onUpdateRequest()
|
|
{
|
|
$data = $this->getData();
|
|
if ($data === null) {
|
|
$row = $this->fetchEntry();
|
|
if ($row === false) {
|
|
throw new NotFoundError('Entry "%s" not found', $this->getIdentifier());
|
|
}
|
|
|
|
$data = get_object_vars($row);
|
|
}
|
|
|
|
$this->setDefaults($data);
|
|
}
|
|
|
|
/**
|
|
* Prepare the form for mode delete
|
|
*
|
|
* Verifies that the repository contains the entry to delete.
|
|
*
|
|
* @throws NotFoundError In case the entry to delete cannot be found
|
|
*/
|
|
protected function onDeleteRequest()
|
|
{
|
|
if (! $this->entryExists()) {
|
|
throw new NotFoundError('Entry "%s" not found', $this->getIdentifier());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Apply the requested mode on the repository
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function onSuccess()
|
|
{
|
|
if ($this->shouldInsert()) {
|
|
return $this->onInsertSuccess();
|
|
} elseif ($this->shouldUpdate()) {
|
|
return $this->onUpdateSuccess();
|
|
} elseif ($this->shouldDelete()) {
|
|
return $this->onDeleteSuccess();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Apply mode insert on the repository
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function onInsertSuccess()
|
|
{
|
|
try {
|
|
$this->insertEntry();
|
|
} catch (Exception $e) {
|
|
Notification::error($this->getInsertMessage(false));
|
|
$this->error($e->getMessage());
|
|
return false;
|
|
}
|
|
|
|
Notification::success($this->getInsertMessage(true));
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Apply mode update on the repository
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function onUpdateSuccess()
|
|
{
|
|
try {
|
|
$this->updateEntry();
|
|
} catch (Exception $e) {
|
|
Notification::error($this->getUpdateMessage(false));
|
|
$this->error($e->getMessage());
|
|
return false;
|
|
}
|
|
|
|
Notification::success($this->getUpdateMessage(true));
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Apply mode delete on the repository
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function onDeleteSuccess()
|
|
{
|
|
try {
|
|
$this->deleteEntry();
|
|
} catch (Exception $e) {
|
|
Notification::error($this->getDeleteMessage(false));
|
|
$this->error($e->getMessage());
|
|
return false;
|
|
}
|
|
|
|
Notification::success($this->getDeleteMessage(true));
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Create and add elements to this form to insert an entry
|
|
*
|
|
* @param array $formData The data sent by the user
|
|
*/
|
|
abstract protected function createInsertElements(array $formData);
|
|
|
|
/**
|
|
* Create and add elements to this form to update an entry
|
|
*
|
|
* Calls createInsertElements() by default. Overwrite this to add different elements when in mode update.
|
|
*
|
|
* @param array $formData The data sent by the user
|
|
*/
|
|
protected function createUpdateElements(array $formData)
|
|
{
|
|
$this->createInsertElements($formData);
|
|
}
|
|
|
|
/**
|
|
* Create and add elements to this form to delete an entry
|
|
*
|
|
* @param array $formData The data sent by the user
|
|
*/
|
|
abstract protected function createDeleteElements(array $formData);
|
|
|
|
/**
|
|
* Create and return a filter to use when selecting, updating or deleting an entry
|
|
*
|
|
* @return Filter
|
|
*/
|
|
abstract protected function createFilter();
|
|
|
|
/**
|
|
* Return a notification message to use when inserting an entry
|
|
*
|
|
* @param bool $success true or false, whether the operation was successful
|
|
*
|
|
* @return string
|
|
*/
|
|
abstract protected function getInsertMessage($success);
|
|
|
|
/**
|
|
* Return a notification message to use when updating an entry
|
|
*
|
|
* @param bool $success true or false, whether the operation was successful
|
|
*
|
|
* @return string
|
|
*/
|
|
abstract protected function getUpdateMessage($success);
|
|
|
|
/**
|
|
* Return a notification message to use when deleting an entry
|
|
*
|
|
* @param bool $success true or false, whether the operation was successful
|
|
*
|
|
* @return string
|
|
*/
|
|
abstract protected function getDeleteMessage($success);
|
|
}
|