mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 01:25:55 +02:00
Added a basic dialog for editing/creating attachmentType elements.
This commit is contained in:
parent
4652339879
commit
3e7150735d
12 changed files with 568 additions and 146 deletions
|
@ -68,8 +68,12 @@ class AjaxUI {
|
|||
* Starts the ajax ui und execute handlers registered in addStartAction().
|
||||
* Should be called in a document.ready, after handlers are set.
|
||||
*/
|
||||
public start()
|
||||
public start(disabled : boolean = false)
|
||||
{
|
||||
if(disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.info("AjaxUI started!");
|
||||
|
||||
this.BASE = $("body").data("base-url") + "/";
|
||||
|
@ -227,6 +231,19 @@ class AjaxUI {
|
|||
{
|
||||
let options : JQueryFormOptions = {
|
||||
success: this.onAjaxComplete,
|
||||
beforeSerialize: function() : boolean {
|
||||
|
||||
//Update the content of textarea fields using CKEDITOR before submitting.
|
||||
|
||||
//@ts-ignore
|
||||
for(let name in CKEDITOR.instances)
|
||||
{
|
||||
//@ts-ignore
|
||||
CKEDITOR.instances[name].updateElement();
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
beforeSubmit: function (arr, $form, options) : boolean {
|
||||
//When data-with-progbar is specified, then show progressbar.
|
||||
if($form.data("with-progbar") != undefined) {
|
||||
|
|
97
src/Controller/AttachmentTypeController.php
Normal file
97
src/Controller/AttachmentTypeController.php
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* part-db version 0.1
|
||||
* Copyright (C) 2005 Christoph Lechner
|
||||
* http://www.cl-projects.de/
|
||||
*
|
||||
* part-db version 0.2+
|
||||
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
||||
* http://code.google.com/p/part-db/
|
||||
*
|
||||
* Part-DB Version 0.4+
|
||||
* Copyright (C) 2016 - 2019 Jan Böhmer
|
||||
* https://github.com/jbtronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
*/
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
|
||||
use App\Entity\AttachmentType;
|
||||
use App\Form\BaseEntityAdminForm;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* @Route("/attachment_type")
|
||||
* @package App\Controller
|
||||
*/
|
||||
class AttachmentTypeController extends AbstractController
|
||||
{
|
||||
/**
|
||||
* @Route("/{id}/edit", requirements={"id"="\d+"}, name="attachment_type_edit")
|
||||
* @Route("/{id}/", requirements={"id"="\d+"})
|
||||
*/
|
||||
public function edit(AttachmentType $entity, Request $request, EntityManagerInterface $em)
|
||||
{
|
||||
|
||||
$form = $this->createForm(BaseEntityAdminForm::class, $entity);
|
||||
|
||||
$form->handleRequest($request);
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em->persist($entity);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
return $this->render('AdminPages/AttachmentTypeAdmin.html.twig', [
|
||||
'entity' => $entity,
|
||||
'form' => $form->createView()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/new")
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function new(Request $request, EntityManagerInterface $em)
|
||||
{
|
||||
$new_entity = new AttachmentType();
|
||||
|
||||
$this->denyAccessUnlessGranted('create', $new_entity);
|
||||
|
||||
$form = $this->createForm(BaseEntityAdminForm::class, $new_entity);
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$em->persist($new_entity);
|
||||
$em->flush();
|
||||
//$this->addFlash('success', $translator->trans('part.created_flash'));
|
||||
|
||||
return $this->redirectToRoute('attachment_type_edit', ['id' => $new_entity->getID()]);
|
||||
}
|
||||
|
||||
return $this->render('AdminPages/AttachmentTypeAdmin.html.twig', [
|
||||
'entity' => $new_entity,
|
||||
'form' => $form->createView()
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Validator\Constraints\NoneOfItsChildren;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
|
|
|
@ -50,9 +50,11 @@ abstract class DBElement
|
|||
* Get the ID. The ID can be zero, or even negative (for virtual elements). If an elemenent is virtual, can be
|
||||
* checked with isVirtualElement().
|
||||
*
|
||||
* @return int the ID of this element
|
||||
* Returns null, if the element is not saved to the DB yet.
|
||||
*
|
||||
* @return int|null the ID of this element
|
||||
*/
|
||||
final public function getID(): int
|
||||
final public function getID(): ?int
|
||||
{
|
||||
return (int) $this->id;
|
||||
}
|
||||
|
|
|
@ -74,20 +74,22 @@ abstract class NamedDBElement extends DBElement
|
|||
|
||||
/**
|
||||
* Returns the last time when the element was modified.
|
||||
* Returns null if the element was not yet saved to DB yet.
|
||||
*
|
||||
* @return \DateTime The time of the last edit.
|
||||
* @return \DateTime|null The time of the last edit.
|
||||
*/
|
||||
public function getLastModified(): \DateTime
|
||||
public function getLastModified(): ?\DateTime
|
||||
{
|
||||
return $this->lastModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the date/time when the element was created.
|
||||
* Returns null if the element was not yet saved to DB yet.
|
||||
*
|
||||
* @return \DateTime The creation time of the part.
|
||||
* @return \DateTime|null The creation time of the part.
|
||||
*/
|
||||
public function getAddedDate(): \DateTime
|
||||
public function getAddedDate(): ?\DateTime
|
||||
{
|
||||
return $this->addedDate;
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\ORM\PersistentCollection;
|
||||
use App\Validator\Constraints\NoneOfItsChildren;
|
||||
|
||||
/**
|
||||
* All elements with the fields "id", "name" and "parent_id" (at least).
|
||||
|
@ -53,6 +53,7 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
|
|||
protected $children;
|
||||
/**
|
||||
* @var StructuralDBElement
|
||||
* @NoneOfItsChildren()
|
||||
*/
|
||||
protected $parent;
|
||||
|
||||
|
@ -85,7 +86,7 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
|
|||
* Check if this element is a child of another element (recursive).
|
||||
*
|
||||
* @param StructuralDBElement $another_element the object to compare
|
||||
* IMPORTANT: both objects to compare must be from the same class (for example two "Device" objects)!
|
||||
* IMPORTANT: both objects to compare must be from the same class (for example two "Device" objects)!
|
||||
*
|
||||
* @return bool True, if this element is child of $another_element.
|
||||
*
|
||||
|
@ -97,10 +98,10 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
|
|||
|
||||
//Check if both elements compared, are from the same type:
|
||||
if ($class_name != \get_class($another_element)) {
|
||||
throw new \InvalidArgumentException('isChildOf() funktioniert nur mit Elementen des gleichen Typs!');
|
||||
throw new \InvalidArgumentException('isChildOf() only works for objects of the same type!');
|
||||
}
|
||||
|
||||
if (null == $this->getID()) { // this is the root node
|
||||
if (null == $this->getParent()) { // this is the root node
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -116,13 +117,13 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
|
|||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Get the parent-ID
|
||||
* Get the parent-ID
|
||||
*
|
||||
* @retval integer * the ID of the parent element
|
||||
* @return integer * the ID of the parent element
|
||||
* * NULL means, the parent is the root node
|
||||
* * the parent ID of the root node is -1
|
||||
*/
|
||||
public function getParentID(): int
|
||||
protected function getParentID(): int
|
||||
{
|
||||
return $this->parent_id ?? self::ID_ROOT_ELEMENT; //Null means root element
|
||||
}
|
||||
|
@ -139,14 +140,12 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
|
|||
|
||||
/**
|
||||
* Get the comment of the element.
|
||||
*
|
||||
* @param bool $parse_bbcode Should BBCode converted to HTML, before returning
|
||||
*
|
||||
|
||||
* @return string the comment
|
||||
*/
|
||||
public function getComment(bool $parse_bbcode = true): string
|
||||
public function getComment(): ?string
|
||||
{
|
||||
return htmlspecialchars($this->comment ?? '');
|
||||
return $this->comment;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,8 +178,6 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
|
|||
* @param string $delimeter the delimeter of the returned string
|
||||
*
|
||||
* @return string the full path (incl. the name of this element), delimeted by $delimeter
|
||||
*
|
||||
* @throws Exception if there was an error
|
||||
*/
|
||||
public function getFullPath(string $delimeter = self::PATH_DELIMITER_ARROW): string
|
||||
{
|
||||
|
@ -189,9 +186,13 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
|
|||
$this->full_path_strings[] = $this->getName();
|
||||
$element = $this;
|
||||
|
||||
while (null != $element->parent) {
|
||||
$overflow = 20; //We only allow 20 levels depth
|
||||
|
||||
while (null != $element->parent && $overflow >= 0) {
|
||||
$element = $element->parent;
|
||||
$this->full_path_strings[] = $element->getName();
|
||||
//Decrement to prevent mem overflow.
|
||||
$overflow--;
|
||||
}
|
||||
|
||||
$this->full_path_strings = array_reverse($this->full_path_strings);
|
||||
|
@ -219,143 +220,31 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
|
|||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* Change the parent ID of this element.
|
||||
*
|
||||
* @param int|null $new_parent_id * the ID of the new parent element
|
||||
* * NULL if the parent should be the root node
|
||||
* Sets the new parent object
|
||||
* @param self $new_parent The new parent object
|
||||
* @return StructuralDBElement
|
||||
*/
|
||||
public function setParentID($new_parent_id): self
|
||||
public function setParent(?self $new_parent) : self
|
||||
{
|
||||
$this->parent_id = $new_parent_id;
|
||||
/*
|
||||
if ($new_parent->isChildOf($this)) {
|
||||
throw new \InvalidArgumentException('You can not use one of the element childs as parent!');
|
||||
} */
|
||||
|
||||
$this->parent = $new_parent;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the comment.
|
||||
*
|
||||
* @param string $new_comment the new comment
|
||||
*
|
||||
* @throws Exception if there was an error
|
||||
* @return StructuralDBElement
|
||||
*/
|
||||
public function setComment(string $new_comment): self
|
||||
public function setComment(?string $new_comment): self
|
||||
{
|
||||
$this->comment = $new_comment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
*
|
||||
* Tree / Table Builders
|
||||
*
|
||||
*********************************************************************************/
|
||||
|
||||
/**
|
||||
* Build a HTML tree with all subcategories of this element.
|
||||
*
|
||||
* This method prints a <option>-Line for every item.
|
||||
* <b>The <select>-tags are not printed here, you have to print them yourself!</b>
|
||||
* Deeper levels have more spaces in front.
|
||||
*
|
||||
* @param int $selected_id the ID of the selected item
|
||||
* @param bool $recursive if true, the tree will be recursive
|
||||
* @param bool $show_root if true, the root node will be displayed
|
||||
* @param string $root_name if the root node is the very root element, you can set its name here
|
||||
* @param string $value_prefix This string is used as a prefix before the id in the value part of the option.
|
||||
*
|
||||
* @return string HTML string if success
|
||||
*
|
||||
* @throws Exception if there was an error
|
||||
*/
|
||||
public function buildHtmlTree(
|
||||
$selected_id = null,
|
||||
bool $recursive = true,
|
||||
bool $show_root = true,
|
||||
string $root_name = '$$',
|
||||
string $value_prefix = ''
|
||||
): string {
|
||||
if ('$$' == $root_name) {
|
||||
$root_name = _('Oberste Ebene');
|
||||
}
|
||||
|
||||
$html = array();
|
||||
|
||||
if ($show_root) {
|
||||
$root_level = $this->getLevel();
|
||||
if ($this->getID() > 0) {
|
||||
$root_name = htmlspecialchars($this->getName());
|
||||
}
|
||||
|
||||
$html[] = '<option value="'.$value_prefix.$this->getID().'">'.$root_name.'</option>';
|
||||
} else {
|
||||
$root_level = $this->getLevel() + 1;
|
||||
}
|
||||
|
||||
// get all subelements
|
||||
$subelements = $this->getSubelements($recursive);
|
||||
|
||||
foreach ($subelements as $element) {
|
||||
$level = $element->getLevel() - $root_level;
|
||||
$selected = ($element->getID() == $selected_id) ? 'selected' : '';
|
||||
|
||||
$html[] = '<option '.$selected.' value="'.$value_prefix.$element->getID().'">';
|
||||
for ($i = 0; $i < $level; ++$i) {
|
||||
$html[] = ' ';
|
||||
}
|
||||
$html[] = htmlspecialchars($element->getName()).'</option>';
|
||||
}
|
||||
|
||||
return implode("\n", $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a template loop for a Breadcrumb bar, representing the structural DB element.
|
||||
*
|
||||
* @param $page string The base page, to which the breadcrumb links should be directing to.
|
||||
* @param $parameter string The parameter, which selects the ID of the StructuralDBElement.
|
||||
* @param bool $show_root Show the root as its own breadcrumb.
|
||||
* @param string $root_name The label which should be used for the root breadcrumb.
|
||||
*
|
||||
* @return array An Loop containing multiple arrays, which contains href and caption for the breadcrumb.
|
||||
*/
|
||||
public function buildBreadcrumbLoop(string $page, string $parameter, bool $show_root = false, $root_name = '$$', bool $element_is_link = false): array
|
||||
{
|
||||
$breadcrumb = array();
|
||||
|
||||
if ('$$' == $root_name) {
|
||||
$root_name = _('Oberste Ebene');
|
||||
}
|
||||
|
||||
if ($show_root) {
|
||||
$breadcrumb[] = array('label' => $root_name,
|
||||
'disabled' => true, );
|
||||
}
|
||||
|
||||
if (!$this->current_user->canDo(static::getPermissionName(), StructuralPermission::READ)) {
|
||||
return array('label' => '???',
|
||||
'disabled' => true, );
|
||||
}
|
||||
|
||||
$tmp = array();
|
||||
|
||||
if ($element_is_link) {
|
||||
$tmp[] = array('label' => $this->getName(), 'href' => $page.'?'.$parameter.'='.$this->getID(), 'selected' => true);
|
||||
} else {
|
||||
$tmp[] = array('label' => $this->getName(), 'selected' => true);
|
||||
}
|
||||
|
||||
$parent_id = $this->getParentID();
|
||||
while ($parent_id > 0) {
|
||||
/** @var StructuralDBElement $element */
|
||||
$element = static::getInstance($this->database, $this->current_user, $this->log, $parent_id);
|
||||
$parent_id = $element->getParentID();
|
||||
$tmp[] = array('label' => $element->getName(), 'href' => $page.'?'.$parameter.'='.$element->getID());
|
||||
}
|
||||
$tmp = array_reverse($tmp);
|
||||
|
||||
$breadcrumb = array_merge($breadcrumb, $tmp);
|
||||
|
||||
return $breadcrumb;
|
||||
}
|
||||
}
|
||||
|
|
76
src/Form/BaseEntityAdminForm.php
Normal file
76
src/Form/BaseEntityAdminForm.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* part-db version 0.1
|
||||
* Copyright (C) 2005 Christoph Lechner
|
||||
* http://www.cl-projects.de/
|
||||
*
|
||||
* part-db version 0.2+
|
||||
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
||||
* http://code.google.com/p/part-db/
|
||||
*
|
||||
* Part-DB Version 0.4+
|
||||
* Copyright (C) 2016 - 2019 Jan Böhmer
|
||||
* https://github.com/jbtronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
*/
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
|
||||
use FOS\CKEditorBundle\Form\Type\CKEditorType;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ResetType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
class BaseEntityAdminForm extends AbstractType
|
||||
{
|
||||
|
||||
protected $security;
|
||||
|
||||
public function __construct(Security $security)
|
||||
{
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$entity = $options['data'];
|
||||
|
||||
$builder
|
||||
->add('name', TextType::class, ['empty_data' => '', 'label' => 'name.label',
|
||||
'attr' => ['placeholder' => 'part.name.placeholder'],
|
||||
'disabled' => !$this->security->isGranted('edit', $entity), ])
|
||||
|
||||
->add('parent', EntityType::class, ['class' => get_class($entity), 'choice_label' => 'full_path',
|
||||
'attr' => ['class' => 'selectpicker', 'data-live-search' => true], 'required' => false, 'label' => 'parent.label',
|
||||
'disabled' => !$this->security->isGranted('move', $entity), ])
|
||||
|
||||
->add('comment', CKEditorType::class, ['required' => false,
|
||||
'label' => 'comment.label', 'attr' => ['rows' => 4], 'help' => 'bbcode.hint',
|
||||
'disabled' => !$this->security->isGranted('edit', $entity)])
|
||||
|
||||
//Buttons
|
||||
->add('save', SubmitType::class, ['label' => 'part.edit.save'])
|
||||
->add('reset', ResetType::class, ['label' => 'part.edit.reset']);
|
||||
}
|
||||
}
|
109
src/Security/Voter/StructureVoter.php
Normal file
109
src/Security/Voter/StructureVoter.php
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* part-db version 0.1
|
||||
* Copyright (C) 2005 Christoph Lechner
|
||||
* http://www.cl-projects.de/
|
||||
*
|
||||
* part-db version 0.2+
|
||||
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
||||
* http://code.google.com/p/part-db/
|
||||
*
|
||||
* Part-DB Version 0.4+
|
||||
* Copyright (C) 2016 - 2019 Jan Böhmer
|
||||
* https://github.com/jbtronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
*/
|
||||
|
||||
namespace App\Security\Voter;
|
||||
|
||||
|
||||
use App\Entity\AttachmentType;
|
||||
use App\Entity\Category;
|
||||
use App\Entity\Device;
|
||||
use App\Entity\Footprint;
|
||||
use App\Entity\Manufacturer;
|
||||
use App\Entity\Storelocation;
|
||||
use App\Entity\Supplier;
|
||||
use App\Entity\User;
|
||||
|
||||
class StructureVoter extends ExtendedVoter
|
||||
{
|
||||
|
||||
/**
|
||||
* Determines if the attribute and subject are supported by this voter.
|
||||
*
|
||||
* @param string $attribute An attribute
|
||||
* @param mixed $subject The subject to secure, e.g. an object the user wants to access or any other PHP type
|
||||
*
|
||||
* @return bool True if the attribute and subject are supported, false otherwise
|
||||
*/
|
||||
protected function supports($attribute, $subject)
|
||||
{
|
||||
$permission_name = $this->instanceToPermissionName($subject);
|
||||
//If permission name is null, then the subject is not supported
|
||||
return ($permission_name !== null) && $this->resolver->isValidOperation($permission_name, $attribute);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a instance type to the permission name.
|
||||
* @param $subject mixed The subject for which the permission name should be generated.
|
||||
* @return string|null The name of the permission for the subject's type or null, if the subject is not supported.
|
||||
*/
|
||||
protected function instanceToPermissionName($subject) : ?string
|
||||
{
|
||||
$class_name = get_class($subject);
|
||||
switch ($class_name) {
|
||||
case AttachmentType::class:
|
||||
return 'attachment_types';
|
||||
case Category::class:
|
||||
return 'categories';
|
||||
case Device::class:
|
||||
return 'devices';
|
||||
case Footprint::class:
|
||||
return 'footprints';
|
||||
case Manufacturer::class:
|
||||
return 'manufacturers';
|
||||
case Storelocation::class:
|
||||
return 'storelocations';
|
||||
case Supplier::class:
|
||||
return 'suppliers';
|
||||
}
|
||||
//When the class is not supported by this class return null
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to voteOnAttribute, but checking for the anonymous user is already done.
|
||||
* The current user (or the anonymous user) is passed by $user.
|
||||
*
|
||||
* @param $attribute
|
||||
* @param $subject
|
||||
* @param User $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function voteOnUser($attribute, $subject, User $user): bool
|
||||
{
|
||||
$permission_name = $this->instanceToPermissionName($subject);
|
||||
//Just resolve the permission
|
||||
return $this->resolver->inherit($user, $permission_name, $attribute) ?? false;
|
||||
}
|
||||
|
||||
|
||||
}
|
54
src/Validator/Constraints/NoneOfItsChildren.php
Normal file
54
src/Validator/Constraints/NoneOfItsChildren.php
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* part-db version 0.1
|
||||
* Copyright (C) 2005 Christoph Lechner
|
||||
* http://www.cl-projects.de/
|
||||
*
|
||||
* part-db version 0.2+
|
||||
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
||||
* http://code.google.com/p/part-db/
|
||||
*
|
||||
* Part-DB Version 0.4+
|
||||
* Copyright (C) 2016 - 2019 Jan Böhmer
|
||||
* https://github.com/jbtronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
*/
|
||||
|
||||
namespace App\Validator\Constraints;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
/**
|
||||
* Constraints the parent property on StructuralDBElement objects in the way, that neither the object self or any
|
||||
* of its children can be assigned.
|
||||
*
|
||||
* @Annotation
|
||||
* @package App\Validator\Constraints
|
||||
*/
|
||||
class NoneOfItsChildren extends Constraint
|
||||
{
|
||||
/** @var string The message used if it is tried to assign a object as its own parent */
|
||||
public $self_message = 'validator.noneofitschild.self';
|
||||
/** @var string The message used if it is tried to use one of the children for as parent */
|
||||
public $children_message = 'validator.noneofitschild.children';
|
||||
|
||||
public function validatedBy()
|
||||
{
|
||||
return parent::validatedBy(); // TODO: Change the autogenerated stub
|
||||
}
|
||||
}
|
88
src/Validator/Constraints/NoneOfItsChildrenValidator.php
Normal file
88
src/Validator/Constraints/NoneOfItsChildrenValidator.php
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
/**
|
||||
*
|
||||
* part-db version 0.1
|
||||
* Copyright (C) 2005 Christoph Lechner
|
||||
* http://www.cl-projects.de/
|
||||
*
|
||||
* part-db version 0.2+
|
||||
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
||||
* http://code.google.com/p/part-db/
|
||||
*
|
||||
* Part-DB Version 0.4+
|
||||
* Copyright (C) 2016 - 2019 Jan Böhmer
|
||||
* https://github.com/jbtronics
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*
|
||||
*/
|
||||
|
||||
namespace App\Validator\Constraints;
|
||||
|
||||
|
||||
use App\Entity\StructuralDBElement;
|
||||
use Symfony\Bundle\MakerBundle\Str;
|
||||
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
|
||||
/**
|
||||
* The validator for the NoneOfItsChildren annotation.
|
||||
* @package App\Validator\Constraints
|
||||
*/
|
||||
class NoneOfItsChildrenValidator extends ConstraintValidator
|
||||
{
|
||||
/**
|
||||
* Checks if the passed value is valid.
|
||||
*
|
||||
* @param mixed $value The value that should be validated
|
||||
* @param Constraint $constraint The constraint for the validation
|
||||
*/
|
||||
public function validate($value, Constraint $constraint)
|
||||
{
|
||||
if (!$constraint instanceof NoneOfItsChildren) {
|
||||
throw new UnexpectedTypeException($constraint, NoneOfItsChildren::class);
|
||||
}
|
||||
|
||||
// custom constraints should ignore null and empty values to allow
|
||||
// other constraints (NotBlank, NotNull, etc.) take care of that
|
||||
if (null === $value || '' === $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if the object is assigned to itself
|
||||
/** @var StructuralDBElement $entity */
|
||||
$entity = $this->context->getObject();
|
||||
/** @var StructuralDBElement $value */
|
||||
|
||||
// Check if the targeted parent is the object itself:
|
||||
$entity_id = $entity->getID();
|
||||
if ($entity_id !== null && $entity_id === $value->getID()) {
|
||||
//Set the entity to a valid state
|
||||
$entity->setParent(null);
|
||||
$this->context->buildViolation($constraint->self_message)->addViolation();
|
||||
//The other things can not happen.
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the targeted parent is a child object
|
||||
if ($value->isChildOf($entity)) {
|
||||
//Set the entity to a valid state
|
||||
$entity->setParent(null);
|
||||
$this->context->buildViolation($constraint->children_message)->addViolation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
5
templates/AdminPages/AttachmentTypeAdmin.html.twig
Normal file
5
templates/AdminPages/AttachmentTypeAdmin.html.twig
Normal file
|
@ -0,0 +1,5 @@
|
|||
{% extends "AdminPages/EntityAdminBase.html.twig" %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-file-alt fa-fw"></i> {% trans %}attachment_type.caption{% endtrans %}
|
||||
{% endblock %}
|
82
templates/AdminPages/EntityAdminBase.html.twig
Normal file
82
templates/AdminPages/EntityAdminBase.html.twig
Normal file
|
@ -0,0 +1,82 @@
|
|||
{% extends "main_card.html.twig" %}
|
||||
|
||||
{% block card_content %}
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-8">
|
||||
|
||||
{{ form_start(form) }}
|
||||
|
||||
<fieldset>
|
||||
<legend>
|
||||
{% if entity.ID %}
|
||||
<strong>{% trans with {'%name': entity.name} %}edit.caption{% endtrans %}</strong>
|
||||
{% else %}
|
||||
<strong>{% trans %}new.caption{% endtrans %}</strong>
|
||||
{% endif %}
|
||||
</legend>
|
||||
|
||||
<ul class="nav nav-tabs mt-2">
|
||||
<li class="nav-item"><a class="link-anchor active nav-link" data-toggle="tab" href="#home">standard.label</a></li>
|
||||
<li class="nav-item"><a data-toggle="tab" class="link-anchor nav-link" href="#info">infos.label</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content mb-3 mt-3">
|
||||
<div id="home" class="tab-pane fade show active">
|
||||
{{ form_row(form.name) }}
|
||||
{{ form_row(form.parent) }}
|
||||
{% block additional_controls %}{% endblock %}
|
||||
{{ form_row(form.comment) }}
|
||||
</div>
|
||||
|
||||
<div id="info" class="tab-pane fade">
|
||||
<div class="form-group row">
|
||||
<label class="col-form-label col-md-3">{% trans %}id.label{% endtrans %}</label>
|
||||
<div class="col-md-9">
|
||||
<p class="form-control-plaintext">{% if entity.iD %}{{ entity.id }}{% else %}-{% endif %}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-form-label col-md-3">{% trans %}createdAt{% endtrans %}</label>
|
||||
<div class="col-md-9">
|
||||
<p class="form-control-plaintext">
|
||||
{% if entity.addedDate %}
|
||||
{{ entity.addedDate | localizeddate("long") }}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-form-label col-md-3">{% trans %}lastModified{% endtrans %}</label>
|
||||
<div class="col-md-9">
|
||||
<p class="form-control-plaintext">
|
||||
{% if entity.lastModified %}
|
||||
{{ entity.lastModified | localizeddate("long") }}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ form_row(form.save) }}
|
||||
{{ form_row(form.reset) }}
|
||||
|
||||
|
||||
|
||||
</fieldset>
|
||||
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
Loading…
Add table
Add a link
Reference in a new issue