I'm trying to let a certain type of user customize the UI of a symfony website. I'm a little bit lost on how can I override the css properties when the form is submitted. Also the data will be saved in AWS S3 cloud. So I will need to create a connector service for this.
I've created a controller, entity, repository and template for this feature.
Here is the controller :
<?php
namespace App\Controller;
use App\Entity\OrganizationCustomization;
use App\Forms\CustomizationFormType;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class OrganizationCustomizationController extends AbstractController
{
/**
* @var LoggerInterface
*/
private $logger;
/**
* @Route("/organization/customization", name="organization_customization")
*
* @param Request $request
*
* @return Response
*/
public function buildForm(
Request $request
) {
//If user do not have permission we redirect him to the dashboard
if (!$this->isGranted('ROLE_COMPANY_MANAGER', '') || !$this->isGranted('ROLE_SUPERADMIN', '')) {
$this->redirectToRoute('dashboard');
}
//Calling the organization customization form
$organizationCustomization = new OrganizationCustomization();
$form = $this->createForm(CustomizationFormType::class, $organizationCustomization);
//Get companyId of the user to set it in OrganizationCustomization entity
$companyId = $this->getUser()->getCompany()->getId();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$organizationCustomization = $form->getData();
$organizationCustomization->setId($companyId);
$organizationCustomization->setIsActive(true);
/** @var UploadedFile $logoFile */
$logoFile = $form['logoFile']->getData();
if ($logoFile) {
$originalFilename = pathinfo($logoFile->getClientOriginalName(), PATHINFO_FILENAME);
// this is needed to safely include the file name as part of the URL
$safeFilename = transliterator_transliterate(
'Any-Latin; Latin-ASCII; [^A-Za-z0-9_] remove; Lower()',
$originalFilename
);
$newFilename = $safeFilename.'-'.uniqid().'.'.$logoFile->guessExtension();
// Move the file to the directory where images are stored
try {
$logoFile->move(
$this->getParameter('company_logo_directory'),
$newFilename
);
} catch (FileException $e) {
// handle exception if something happens during file upload
$this->logger->info('File upload has failed '.$e);
}
// updates the 'logoFilename' property to store the PDF file name
// instead of its contents
$organizationCustomization->setLogoFile($newFilename);
dump($organizationCustomization);
}
}
return $this->render('organization_customization/index.html.twig', [
'form' => $form->createView(),
]);
}
}
Here is the entity :
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\OrganizationCustomizationRepository")
*/
class OrganizationCustomization
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=7, nullable=true)
*/
private $backgroundColor;
/**
* @ORM\Column(type="string", length=7, nullable=true)
*/
private $fontColor;
/**
* @ORM\Column(type="string", length=7, nullable=true)
*/
private $baseSiteColor;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $logoFile;
/**
* @ORM\Column(type="boolean")
*/
private $isActive;
public function getId(): ?int
{
return $this->id;
}
public function setId(?int $id): self
{
$this->id = $id;
return $this;
}
public function getBackgroundColor(): ?string
{
return $this->backgroundColor;
}
public function setBackgroundColor(?string $backgroundColor): self
{
if (true === \mb_strpos($backgroundColor, '#')) {
$this->backgroundColor = $backgroundColor;
}
return $this;
}
public function getFontColor(): ?string
{
return $this->fontColor;
}
public function setFontColor(?string $fontColor): self
{
if (true === \mb_strpos($fontColor, '#')) {
$this->fontColor = $fontColor;
}
return $this;
}
public function getBaseSiteColor(): ?string
{
return $this->baseSiteColor;
}
public function setBaseSiteColor(?string $baseSiteColor): self
{
if (true === \mb_strpos($baseSiteColor, '#')) {
$this->baseSiteColor = $baseSiteColor;
}
return $this;
}
public function getLogoFile(): ?string
{
return $this->logoFile;
}
public function setLogoFile(?string $logoFile): self
{
$this->logoFile = $logoFile;
return $this;
}
public function getIsActive(): ?bool
{
return $this->isActive;
}
public function setIsActive(bool $isActive): self
{
$this->isActive = $isActive;
return $this;
}
}
And here is my template:
{% block headtop %}
<title>{% block title %}Harmonie Technologie{% endblock %}</title>
{% include "head.html.twig" %}
{% endblock headtop %}
{% include "css.html.twig" %}
<body>
{% block body %}
{#{{ form(form.backgroundColor, {attr: {class: 'customize-background-color'}}) }}
{{ form(form.fontColor) }}
{{ form(form.baseSiteColor) }}
{{ form(form.logoFile) }}#}
{{ form(form) }}
{% endblock %}
</body>
For now I'm getting the right values when I submit the form but i'm trying to override the templates/css.html.twig that is only containing this :
<link href="{{absolute_url("/bootstrap/css/bootstrap.min.css")}}" rel="stylesheet"/>
<link href="{{absolute_url("/fontawesome-5.6.3/css/all.min.css")}}" rel="stylesheet">
<link href="{{absolute_url("/jquery-ui-1.12.1.custom/jquery-ui.min.css")}}" rel="stylesheet">
<link href="{{absolute_url("/jquery-ui-1.12.1.custom/jquery-ui.structure.min.css")}}" rel="stylesheet">
<link href="{{absolute_url("/css/riskandme.css")}}" rel="stylesheet">
<link href="{{absolute_url('/css/bootstrap-datetimepicker.css')}}" rel="stylesheet"/>
Thank you a lot for you attention and help.
If you want to keep user preferences you need to persist it in database. There are some possibilities.
@Wouter J used that:
1)Create a stylesheet, for instance styles.css.twig and put the content there. For instance:
.user-color{
color: {{ user_color }};
}
Now, create a class which renders this file and saves it somewhere:
class TemplateRenderer
{
protected $basepath;
protected $templating;
protected $parameters = array();
public function __construct($templating, $basepath, $styleseheetpath)
{
$this->basepath = $basepath; /* "%kerel.base_path" parameter */
$this->templating = $templating; /* "twig" service */
$this->stylesheetpath = $stylesheetpath; /* custom defined parameter */
}
public function setParam($id, $value)
{
$this->parameters[$id] = $value;
}
public function render()
{
file_put_contents(
$this->basepath.'/web/assets/css/styles.css',
$this->templating->render(
$this->stylesheetpath,
$this->parameters
)
);
}
}
Register this class as a service and register it as an after event listener ( http://symfony.com/doc/current/cookbook/event_dispatcher/before_after_filters.html ).
From your controller (or from the event config file using method injection), you can call the setParam method to set a variable.
Inside your base html file, you can include this file using it's path (now, web/assets/css/styles.css).
Please note that the code is an example. Some error handling and caching is definitely needed to make this usable in production.
Source: Symfony2: Use Twig variable in stylesheet
2)You can use the twig "include with":
{% include 'style.css' with {'color': user.color} %}
Source: https://twig.symfony.com/doc/2.x/tags/include.html
3)You could use different preformatted css files:
For example you could have a field "ui_color" in database. The user can submit a form and choose "green" or "orange".
You have two css files, one is "green-theme.css", the other one is"orange-theme.css".
Then you call it in your twig file like:
{% include myUser.ui_color ~ ".css" %}
4) you could use inline css in your twig file, and use twig variables to modify somes values in it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.