Multiple file upload constraint - symfony

I'm followed the tutorial to manage the upload of multiple files http://growingcookies.com/easy-multiple-file-upload-in-symfony-using-the-collectiontype-field/
The system for uploading multiple files works fine.
However, I would like to add a constraint to allow only certain types of files and to set a maximum size.
For that, I add #Assert\File:
/**
* #Assert\File(
* maxSize = "300k",
* mimeTypes = {"application/pdf", "application/x-pdf", "text/plain", "application/msword",
* "application/vnd.ms-excel", "image/jpeg", "image/x-citrix-jpeg", "image/png", "image/x-citrix-png", "image/x-png", "image/gif",
* "application/zip"},
* mimeTypesMessage = "Liste des formats de fichiers acceptés : PDF, TXT, DOC, XLS, JPG, PNG, GIF"
* )
*
* #ORM\OneToMany(targetEntity="Maps_red\TicketingBundle\Entity\TicketDocument", mappedBy="ticket", cascade={"persist"}, orphanRemoval=true)
*/
protected $documents;
By adding that, the code does not work anymore. I get the following error :
Impossible to access an attribute ("name") on a null variable.
This error appears on the Add Files page when I send the form. The line corresponding to the error is:
<div class="col col-xs-11" id="jsPreview{{ pos }}">{{ doc.vars.value.name }}</div>
The constraint violation message is : "The file could not be found."
Do you know where my error is ?
Edit for #Denis Alimov:
I tried the answer of Denis Alimov with #Assert\All but it returns the same error.
I then tried to put the constraint in the BuildForm. Now, the .txt files pass without error, but all the other extensions always return me the same error
Impossible to access an attribute ("name") on a null variable.
Edit for #Jakumi:
My twig :
{% extends '#Ticketing/base.html.twig' %}
{% block title %}{{ 'New Ticket'|trans({}, 'TicketingBundle') }}{% endblock %}
{% block header %}<h1>{{ 'New Ticket'|trans({}, 'TicketingBundle') }}</h1>{% endblock %}
{% block form_group_class -%}
col-sm-8
{%- endblock form_group_class %}
{% block main %}
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
{% form_theme form 'bootstrap_4_layout.html.twig' _self %}
<div class="box box-danger">
<div class="box-header with-border">
<h3 class="box-title">{{ 'Create a new ticket'|trans({}, 'TicketingBundle') }}</h3>
</div>
{% form_theme form 'bootstrap_3_horizontal_layout.html.twig' _self %}
{{ form_start(form, {'attr': {'class': 'form-horizontal'} }) }}
<div class="box-body">
<div class="hr-line-dashed"></div>
<div id="filesProto" data-prototype="{{ form_widget(form.documents.vars.prototype)|e }}"></div>
<div class="form-group">
<label class="col-sm-2 control-label" for="ticket_form_documents">Pièce-jointe</label>
<div class="col-sm-8" id="filesBox">
{% set pos = 0 %}
{% for doc in form.documents %}
<div class="row">
<div class="col col-xs-1" id="jsRemove{{ pos }}" style="">
<button type="button" class="btn btn-danger" onclick="removeFile($(this));"><i class="fa fa-times" aria-hidden="true"></i></button>
</div>
<div class="col col-xs-11" id="jsPreview{{ pos }}">{{ doc.vars.value.name }}</div>
<div style="display:none">
{{ form_widget(doc) }}
</div>
</div>
{% set pos = pos + 1 %}
{% endfor %}
</div>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<div class="col-md-offset-2 col-sm-8">
<button id="dropbutton" class="btn bg-ticketing btn-flat form-control" type="submit">
{{ 'Submit the ticket'|trans({}, 'TicketingBundle') }}
</button>
</div>
</div>
<!-- /.box-footer -->
{{ form_end(form) }}
</div>
<script>
var fileCount = '{{ form.documents|length }}';
var removeButton = "<button type='button' class='btn btn-danger btn-xs' onclick='removeFile($(this));'><i class='fa fa-times' aria-hidden='true'></i></button>";
function removeFile(ob)
{
ob.parent().parent().remove();
}
function createAddFile(fileCount)
{
// grab the prototype template
var newWidget = $("#filesProto").attr('data-prototype');
// replace the "__name__" used in the id and name of the prototype
newWidget = newWidget.replace(/__name__/g, fileCount);
newWidget = "<div style='display:none'>" + newWidget + "</div>";
hideStuff = "";
hideStuff += "<div class='col col-xs-1' id='jsRemove" + fileCount + "' style='display: none;'>";
hideStuff += removeButton;
hideStuff += "</div>";
hideStuff += "<div class='col col-xs-11' id='jsPreview" + fileCount + "'>";
hideStuff += "</div>";
hideStuff += "<div class='col-sm-8'>";
hideStuff += "<button type='button' id='jsBtnUpload" + fileCount + "' class='btn btn-default'>";
hideStuff += "<i class='fa fa-plus'></i> {{ 'Pièce-jointe' | trans }}";
hideStuff += "</button>";
hideStuff += "</div>";
$("#filesBox").append("<div class='form-group'>" + hideStuff + newWidget + "</div>");
// On click => Simulate file behaviour
$("#jsBtnUpload" + fileCount).on('click', function(e){
$('#ticket_form_documents_' + fileCount + '_file').trigger('click');
});
// Once the file is added
$('#ticket_form_documents_' + fileCount + '_file').on('change', function() {
// Show its name
fileName = $(this).prop('files')[0].name;
$("#jsPreview" + fileCount).append(fileName);
// Hide the add file button
$("#jsBtnUpload" + fileCount).hide();
// Show the remove file button
$("#jsRemove" + fileCount).show();
// Create another instance of add file button and company
createAddFile(parseInt(fileCount)+1);
});
}
$(document).ready(function(){
createAddFile(fileCount);
fileCount++;
});
</script>
{% endblock %}
Edit :
With {{ doc.vars.value.name ?? '' }} I do not have the error anymore !!
However, the file deletion buttons remain displayed:
<div class="col col-xs-1" id="jsRemove1" style="">
<button type="button" class="btn btn-danger" onclick="removeFile($(this));"><i class="fa fa-times" aria-hidden="true"></i></button>
</div>
How to make these buttons disappear when a file type is not good?

As already mentioned use All constraint like this
/**
* #Assert\All({
* #Assert\File(
* maxSize = "300k",
* mimeTypes = {"application/pdf", "application/x-pdf", "text/plain", "application/msword", "application/vnd.ms-excel", "image/jpeg", "image/x-citrix-jpeg", "image/png", "image/x-citrix-png", "image/x-png", "image/gif","application/zip"},
* mimeTypesMessage = "Liste des formats de fichiers acceptés : PDF, TXT, DOC, XLS, JPG, PNG, GIF"
* )
* })
*/
private $documents;
Also you can add constraints to your DocumentType in the buildForm method

Related

Search function in Flask with SQLite

I have a problem in my search function. The search result was not displayed in my web application. I'm trying to search words based on the brand or model. I have no idea what did I make mistake.
This is the backend in app.py
#app.route('/search',methods = ['GET','POST'])
def search():
result = request.form.get('search')
conn = get_db_connection()
searchsmartphones = conn.execute("SELECT * FROM Smartphone WHERE brand OR model = ?",(result,))
conn.commit()
return render_template('smartphone.html',searchsmartphones = searchsmartphones)
This is the search form
<form action="/search" method="GET">
<div class="mb-5 d-flex position-relative">
<!-- Search -->
<div class="input-group w-50 mx-auto">
<input class="form-control py-2" placeholder="Search for smartphone" name="search" value="" />
<button type="submit" class="btn btn-secondary text-muted">Search</button>
</div>
</div>
</form>
This is the output result
<div class="d-flex">
{% for smartphone in searchsmartphones %}
<div class="row row-cols-4 mb-5">
<div class="card mr-5" style="width: 20rem;">
<a href="#">
<img src="{{ url_for('static',filename = smartphone['image_URL']) }}" class="card-img-top" style="height: 250px;">
</a>
<div class="card-body">
<a href="#">
<h5 class="card-title">{{ smartphone['model'] }}</h5>
</a>
<div class="mt-5 d-flex justify-content-between">
<p class="text-muted">{{ smartphone['brand'] }}</p>
<p class="fw-bold">{{ smartphone['lowprice'] }} - {{ smartphone['highprice'] }}</p>
</div>
</div>
</div>
</div>
<div class="col-md-auto">
</div>
{% endfor %}
</div>
Traceback (most recent call last):
File "C:\Users\user\desktop\phonebuddy\.venv\lib\site-packages\flask\app.py", line 2525, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\user\desktop\phonebuddy\.venv\lib\site-packages\flask\app.py", line 1822, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\user\desktop\phonebuddy\.venv\lib\site-packages\flask\app.py", line 1820, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\user\desktop\phonebuddy\.venv\lib\site-packages\flask\app.py", line 1796, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "C:\Users\user\Desktop\PhoneBuddy\app.py", line 94, in search
searchsmartphones = conn.execute("SELECT * FROM Smartphone WHERE brand LIKE '%?%' OR model LIKE '%?%'",(result,result))
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 2 supplied.
127.0.0.1 - - [27/Nov/2022 22:15:14] "GET /search?search=Apple&sort=low HTTP/1.1" 500 -
Empty when using my original code
The error indicates that we did not pass enough parameters to the select query. I found that we cannot use %?% directly.
Example of using Flask and Sqlite3 for search query
I reproduced the scenario with dummy data and dummy SQL schema. The SQL schema and dummy query insertion happens at the first view of the root / path. The search path is defined in /search route.
File structure:
.
├── app.py
├── mobile_devices.db
├── schema.sql
├── templates
│   ├── home.html
│   └── search.html
schema.sql:
CREATE TABLE IF NOT EXISTS Smartphone (
id INTEGER PRIMARY KEY AUTOINCREMENT,
brand TEXT NOT NULL,
model TEXT NOT NULL,
lowprice DOUBLE NOT NULL
);
app.py:
from flask import Flask, render_template, g, request
import sqlite3
DATABASE = 'mobile_devices.db'
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your secret key'
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect(DATABASE)
db.row_factory = sqlite3.Row
return db
#app.teardown_appcontext
def close_connection(exception):
db = getattr(g, '_database', None)
if db is not None:
db.close()
def query_db(query, args=(), one=False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
def insert_db(query, args=()):
msg = ""
with app.app_context():
try:
db = get_db()
cur = db.cursor()
cur.execute(query, args)
db.commit()
msg = "Insertion successful"
except Exception as ex:
msg = f"Insertion failed: {str(ex)}"
finally:
print(msg)
def init_db():
with app.app_context():
db = get_db()
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
init_db()
def insert_dummy_values():
insert_db(
"INSERT INTO Smartphone (brand, model, lowprice) VALUES (?,?,?)",
("Nokia", "C6", 150))
insert_db(
"INSERT INTO Smartphone (brand, model, lowprice) VALUES (?,?,?)",
("Samsung", "Fold", 250))
insert_db(
"INSERT INTO Smartphone (brand, model, lowprice) VALUES (?,?,?)",
("Nokia", "N95", 300))
insert_db(
"INSERT INTO Smartphone (brand, model, lowprice) VALUES (?,?,?)",
("Sony", "Samsung", 1250))
#app.route('/')
def show_home():
smart_phones = query_db('select brand, model, lowprice from Smartphone')
if len(smart_phones) == 0:
insert_dummy_values()
smart_phones = query_db('select brand, model, lowprice from Smartphone')
return render_template('home.html', smart_phones=smart_phones)
#app.route('/search', methods=['GET', 'POST'])
def search():
if request.method == "POST":
search_value = request.form.get('search_brand_model')
print(search_value)
smart_phones = query_db(
"SELECT * FROM Smartphone WHERE brand LIKE ? OR model LIKE ?",
('%' + search_value + '%', '%' + search_value + '%'))
return render_template('search.html', searchsmartphones=smart_phones)
else:
return render_template('search.html')
templates/home.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
{% if smart_phones%}
Total smartphones in DB: {{ smart_phones | length }}
<ul>
{% for smartphone in smart_phones %}
<li> {{ smartphone['brand'] }} {{ smartphone['model'] }} :
${{ smartphone['lowprice'] }}
</li>
{% endfor %}
</ul>
{% else %}
<p>No smartphone in db</p>
{% endif %}
</body>
</html>
templates/search.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Search</title>
</head>
<body>
<form action="/search" method="POST">
<div class="mb-5 d-flex position-relative">
<!-- Search -->
<div class="input-group w-50 mx-auto">
<input class="form-control py-2"
placeholder="Search for smartphone" name="search_brand_model" value=""/>
<button type="submit" class="btn btn-secondary text-muted">Search
</button>
</div>
</div>
</form>
{% if searchsmartphones %}
<div class="d-flex">
{% for smartphone in searchsmartphones %}
<div class="row row-cols-4 mb-5">
<div class="card mr-5" style="width: 20rem;">
<div class="card-body">
<a href="#">
<h5 class="card-title">{{ smartphone['model'] }}</h5>
</a>
<div class="mt-5 d-flex justify-content-between">
<p class="text-muted">{{ smartphone['brand'] }}</p>
<p class="fw-bold">{{ smartphone['lowprice'] }}</p>
</div>
</div>
</div>
</div>
<div class="col-md-auto">
</div>
{% endfor %}
</div>
{% endif %}
</body>
</html>
Screenshots:
Initial database rows:
Search using Brand Nokia:
Search using model n95:

How can i style my django filter with bootstrap or CSS

i'm new to django here and still learning. So, i created a filter using django-filter and i didn't know how to style it (bootstrap or CSS) because i really don't like the default styling. Can anyone help me with it? i already googled it but didn't find anything useful.
filters.py
`
class CompLink_Filter(django_filters.FilterSet):
start_date = DateFilter(field_name="date_added", label='Date ajout' ,lookup_expr='gte')
company_name = CharFilter(field_name='company_name', label='Nom Entreprise' ,lookup_expr='icontains')
sector = CharFilter(field_name='sector',label='Secteur' , lookup_expr='icontains')
size = CharFilter(field_name='size', label='Taille' ,lookup_expr='icontains')
phone = CharFilter(field_name='phone', label='Téléphone' ,lookup_expr='icontains')
employees_on_linkedin = CharFilter(field_name='employees_on_linkedin', label='Employés sur Linkedin :' ,lookup_expr='icontains')
type = CharFilter(field_name='type', label='Type' ,lookup_expr='icontains')
founded_in = CharFilter(field_name='founded_in', label='Fondée En' ,lookup_expr='icontains')
specializations = CharFilter(field_name='specializations', label='Spécialisations' ,lookup_expr='icontains')
class Meta:
model = Comapny_Profile
fields= '__all__'
exclude= ['company_link','website','head_office','address']`
displaying the filter in my template:
<form class="" action="" method="get">
{% for field in myFilter.form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
<button class="btn btn-primary" type="submit" name="button">Recherche</button>
</form>
You could use jQuery or javascript to manipulate the DOM. When the tags are created you can style it. For example.
$("input").addClass("form-group");

Did we migrate incorrectly? Validation not happening in forms migrated from Symfony 2.7 to 4.0

In code migrated from Symfony 2.7 to 4.0, validation no longer happens on my form, allowing bad data to pass through and cause a Doctrine constraint violation
I'm new to Symfony and was asked to migrate a 2.7 application to 4.0. I did this in steps (2.7->2.8->3.x->4.0) and addressed issues as they came up, but one thing that broke along the way is automatic form validation. In the original version, if I attempted to create a new user and left the fields blank, it would correctly flag those and pop up " must not be empty" messages in the UI. Now, it lets those past until it attempts to write to the database, at which point Doctrine barfs because the database not null constraints are violated.
I've tried to figure out what I'm doing wrong, but I don't have a firm grasp on how the form creation process and syntax has changed. All of the example documentation on validation in forms assumes the createFormBuilder() approach, and all my existing code uses createForm(). What am I missing?
Here's part of the user object associated with the form showing the #Assert statements that I expect to trigger validation warnings:
/**
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Domain\CoreBundle\Repository\UserRepository")
* #ORM\HasLifecycleCallbacks()
* #UniqueEntity(fields="email", message="This email address is already in usage")
* #UniqueEntity(fields="username", message="This username is already in usage")
*/
class User extends BaseUser implements JsonSerializable
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #Assert\NotBlank(message="Email should not be empty")
* #Assert\Email(strict=true)
* #Assert\Length(max=150, maxMessage="Email should be less than {{ limit }} characters")
*/
protected $email;
/**
* #Assert\NotBlank(message="Username should not be empty")
* #Assert\Regex(
* pattern = "/^\d*[a-zA-Z][ a-zA-Z0-9\!\#\#\$\%\^\&\-\_\=\+\~\?\.]*$/i",
* message = "Username should include at least one letter"
* )
*/
protected $username;
/**
* #var string
*
* #Assert\NotBlank(message="First name should not be empty")
* #ORM\Column(name="first_name", type="string", length=255)
*/
protected $firstName;
/**
* #var string
*
* #Assert\NotBlank(message="Last name should not be empty")
* #ORM\Column(name="last_name", type="string", length=255)
*/
protected $lastName;
(rest of code omitted for conciseness)
And here's the addNew action from the controller (AdministratorController extends UserController):
/**
* Add new administrator
*
* #param Request $request
*
* #return Response
*/
public function addNewAction(Request $request)
{
$company = $this->getCurrentCompany();
$form = $this->createForm(AddAdministratorType::class, null,
array('current_user'=> $this->user, 'restricted_admin'=>$this->getRestrictedAdmin(), 'company'=>$company));
if ($request->getMethod() == Request::METHOD_POST) {
$form->handleRequest($request);
// check if the user already exists
$userManager = $this->get('fos_user.user_manager');
$user = $form->getData();
$oldUser = $userManager->findUserByUsername($user['email']);
if ($oldUser)
{
$alreadyExists = false;
if ($user["isSuperAdmin"] &&$oldUser->isGrantedSuperAdmin())
$alreadyExists = true;
if ($user["isCompanyAdmin"] && $oldUser->isGranted(UserRepository::ROLE_COMPANY_ADMIN, $company))
$alreadyExists = true;
if (!$user["isCompanyAdmin"] && !$user["isSuperAdmin"] && $oldUser->isGranted(UserRepository::ROLE_ADMIN,$company))
$alreadyExists = true;
if ($alreadyExists)
$form->get('email')->addError(new FormError('This email address is already in use'));
}
if ($form->isValid()) {
$user = $form->getData();
if ($oldUser) // if the user already exists, we just need to add the role
{
if (!$this->getUser()->isGrantedSuperAdmin() &&
!in_array($company->getId(), array_map(function($x){return $x->getId();}, $oldUser->getCompaniesWithRole())))
{
// the user isn't currently in this company and the user adding the role
// isn't a super admin, so we have to create a shadow user entry to hide
// the real user info from other in the company until the user logs into
// the company
$oldShadow=$this->em->getRepository(ShadowUser::class)->findOneBy(array("user" => $oldUser, "company"=>$company));
if (!$oldShadow)
{
$shadow = new ShadowUser();
$shadow->setUser($oldUser);
$shadow->setFirstName($user["firstName"]);
$shadow->setLastName($user["lastName"]);
$shadow->setCompany($company);
$shadow->setIsVydioUsed($user["isVydioUsed"]);
$shadow->setVydioRoomLink($user["vydioRoomLink"]);
$shadow->setCreatedDate(new \DateTime());
$this->em->persist($shadow);
}
}
if ($user["isSuperAdmin"])
{
$oldUser->addMyRole(UserRepository::ROLE_SUPER_ADMIN, $company);
$this->get('pp_mailer')->onAddNewRole($oldUser,UserRepository::ROLE_SUPER_ADMIN, $company );
}
if ($user["isCompanyAdmin"])
{
$oldUser->addMyRole(UserRepository::ROLE_COMPANY_ADMIN, $company);
$this->get('pp_mailer')->onAddNewRole($oldUser,UserRepository::ROLE_COMPANY_ADMIN, $company );
}
if (!$user["isSuperAdmin"] && !$user["isCompanyAdmin"])
{
$oldUser->addMyRole(UserRepository::ROLE_ADMIN, $company);
$this->get('pp_mailer')->onAddNewRole($oldUser,UserRepository::ROLE_ADMIN, $company );
}
$programRepo = $this->em->getRepository(ProgramUser::class);
foreach($user["programs"] as $program)
{
$oldRelation = $programRepo->findOneBy(array("user"=> $oldUser, "program"=>$program));
if (!$oldRelation)
{
$relation = new ProgramUser();
$relation->setUser($oldUser);
$relation->setProgram($program);
$relation->setCompany($company);
$this->em->merge($relation);
}
}
$this->em->persist($oldUser);
$this->em->flush();
}
else
{
$newUser = new User();
$newUser->setPassword($this->get('domain_core_service')->generatePassword());
$newUser->setDefaultCompany($company);
$newUser->setFirstName($user["firstName"]);
$newUser->setLastName($user["lastName"]);
$newUser->setEmail($user["email"]);
$newUser->setUsername($user["email"]);
$newUser->setEnabled($user["enabled"]);
$newUser = $this->em->getRepository('DomainCoreBundle:User')->addUserInSystem($userManager, $newUser);
$token = $this->get('domain_core_service')->generateToken();
$newUser->setConfirmationToken($token);
if ($user["isSuperAdmin"])
{
$newUser->addMyRole(UserRepository::ROLE_SUPER_ADMIN, $company);
$this->get('pp_mailer')->onAddNewUser($newUser,UserRepository::ROLE_SUPER_ADMIN, $company );
}
if ($user["isCompanyAdmin"])
{
$newUser->addMyRole(UserRepository::ROLE_COMPANY_ADMIN, $company);
$this->get('pp_mailer')->onAddNewUser($newUser,UserRepository::ROLE_COMPANY_ADMIN, $company );
}
if (!$user["isSuperAdmin"] && !$user["isCompanyAdmin"])
{
$newUser->addMyRole(UserRepository::ROLE_ADMIN, $company);
$this->get('pp_mailer')->onAddNewUser($newUser,UserRepository::ROLE_ADMIN, $company );
}
foreach($user["programs"] as $program)
{
$relation = new ProgramUser();
$relation->setUser($newUser);
$relation->setProgram($program);
$relation->setCompany($company);
$this->em->merge($relation);
}
$this->em->persist($newUser);
$this->em->flush();
}
return $this->redirect($this->generateUrl('domain_admin_show_all_administrators_page'));
}
}
return $this->render(
'DomainAdminBundle:Administrators:add-new.html.twig',
array(
'form' => $form->createView(),
'page_title' => 'Add New Administrator',
'currentSidebar' => $this->currentSideBar,
'currentSidebarItem' => $this->currentSidebarItem,
)
);
}
And the twig file for the form:
{% extends 'DomainAdminBundle::base-admin-layout.html.twig' %}
{% import '::widgets/form_errors.html.twig' as form_custom_errors %}
{% import '::widgets/label.html.twig' as form_custom_labels %}
{% block title %} My Application| {{ page_title }} {% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript" src="{{ asset('assets/scripts/admin-add-new.js') }}"></script>
{% endblock %}
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" type="text/css" href="{{ asset('assets/styles/admin-add-new.css') }}">
{% endblock %}
{% block admin_main_content %}
<div class="content-block administrator-controller" ng-controller="AdministratorController">
<div class="content-title-bar">
<div class="pull-left">
<h2>{{ page_title }}</h2>
</div>
</div>
<div class="content-block" ng-controller="AdminController">
{{ form_start(form, {"attr": { "action":"{{ path('domain_admin_add_new_administrator_page') }}", 'enctype': 'multipart/form-data', "method":"POST", "novalidate":"novalidate", "autocomplete":"off", "class":"form-horizontal add-user", "ng-submit":"disableAddButton()" }}) }}
<div class="base-box info-block">
<div class="control-group">
<div class="controls">
{{ form_widget(form.enabled) }}
{{ form_label(form.enabled, 'Active') }}
</div>
</div>
{% if app.user.isGrantedSuperAdmin() %}
<div class="control-group">
<div class="controls">
{% set companyAdminValue = form.isCompanyAdmin.vars.checked ? 'true' : 'false' %}
{{ form_widget(form.isCompanyAdmin, { 'attr':{ 'ng-model':'adminForm.isCompanyAdmin', 'ng-init': 'adminForm.isCompanyAdmin=' ~ companyAdminValue } }) }}
{{ form_label(form.isCompanyAdmin, 'Company Admin') }}
{% set superAdminValue = form.isSuperAdmin.vars.checked ? 'true' : 'false' %}
{{ form_widget(form.isSuperAdmin, { 'attr':{ 'ng-model':'adminForm.isSuperAdmin', 'ng-init': 'adminForm.isSuperAdmin=' ~ superAdminValue } }) }}
{{ form_label(form.isSuperAdmin, 'Super Admin') }}
</div>
</div>
{% endif %}
<div class="control-group" ng-init="initMultiSelect(true)">
{{ form_custom_labels.widget(form.programs) }}
<div class="controls">
{{ form_widget(form.programs) }}
{{ form_custom_errors.widget(form.programs) }}
</div>
</div>
<div class="control-group">
{{ form_custom_labels.widget(form.firstName) }}
<div class="controls">
{{ form_widget(form.firstName) }}
{{ form_custom_errors.widget(form.firstName) }}
</div>
</div>
<div class="control-group">
{{ form_custom_labels.widget(form.lastName) }}
<div class="controls">
{{ form_widget(form.lastName) }}
{{ form_custom_errors.widget(form.lastName) }}
</div>
</div>
<div class="control-group">
{{ form_custom_labels.widget(form.email) }}
<div class="controls">
{{ form_widget(form.email) }}
{{ form_custom_errors.widget(form.email) }}
</div>
</div>
<div class="control-group">
{{ form_custom_labels.widget(form.timezone) }}
<div class="controls">
{{ form_widget(form.timezone) }}
{{ form_custom_errors.widget(form.timezone) }}
</div>
</div>
</div>
<div class="text-right">
<button id="add-admin-submit" type="submit" class="btn btn-do" ng-disabled="isDisabled">Add new administrator</button>
Cancel
</div>
{{ form_rest(form) }}
{{ form_end(form) }}
</div>
</div>
{% endblock %}
If I leave all fields blank and click "Add New Administrator" it doesn't flag them as blank, instead passing them onto Doctrine. The expected behavior is that it flags them at the UI and doesn't attempt to write them to the database.
I'm sure I've created multiple crimes against Symfony as I've ramped up the learning curve, so go easy. Right now I'm just trying to address this narrow issue; refactoring to more elegantly fit Symfony 4 will have to wait for another day.
Thanks!
Looks like you want to validate the User class against the data from your request.
Have you set data_class option in your form type class?
It's required if you want to use validation rules from another class (as you marked your properties with some #Assert* annotations).
https://symfony.com/doc/current/forms.html#creating-form-classes
Another way to do validation is to choose validation rules right in your FormType.

symfony3 session parameter: adress['livraison'] give null value

I am experimenting with the implementation of ecommerce "DevAndClick". I cannot retrieve the delivery and billing addresses, and the session address[livraison] displays a null value. I am blocked. Has anyone ever met this problem that can help me?
Here is code of the form of the Twig view:
<form action="{{path('validation')}}" method="POST">
<h4>Adresse de livraison</h4>
{% for adresse in utilisateur.adresses %}
<label class="radio">
<input type="radio" name="livraison" value="{{adresse.id}}" {% if loop.index0 == 0 %} checked="checked" {% endif %} >
{{adresse.adresse}} , {{adresse.cp}} {{adresse.ville}}-{{adresse.pays}}<i class="icon-trash"></i> <br />
{{adresse.prenom}} {{adresse.nom}}
</label>
{% endfor %}
<br /><br />
<h4>Adresse de facturation</h4>
{% for adresse in utilisateur.adresses %}
<label class="radio">
<input type="radio" name="facturation" value="{{adresse.id}}" {% if loop.index0 == 0 %} checked="checked" {% endif %} >
{{adresse.adresse}} , {{adresse.cp}} {{adresse.ville}}-{{adresse.pays}}<i class="icon-trash"></i> <br />
{{adresse.prenom}} {{adresse.nom}}
</label>
{% endfor %}
<button class="btn btn-primary">Valider mes adresse </button>
</form>
Here are the two methods of my controller:
public function setLivraisonOnSession(Request $request)
{
$session = $request->getSession();
if(!$session->has('adresse')) $session->set('adresse',array());
$adresse = $session->get('adresse');
if($request->request->get('livraison') != null && $request->request->get('facturation') != null )
{
$adresse['livraison'] = $request->request->get('livrasion');
$adresse['facturation'] = $request->request->get('facturation');
}
else{
return $this->redirect($this->generateUrl('validation'));
}
$session->set('adresse',$adresse);
return $this->redirect($this->generateUrl('validation'));
}
public function validationAction(Request $request)
{
if($request->isMethod('POST'))
$this->setLivraisonOnSession($request);
$em = $this->getDoctrine()->getManager();
$session = $request->getSession();
$adresse = $session->get('adresse');
//var_dump($adresse['livraison']);
// die();
$produits = $em->getRepository('EcommerceBundle:Produits')->findArray(array_keys($session->get('panier')));
$livraison = $em->getRepository('EcommerceBundle:UtilisateursAdresses')->find($adresse['livraison']);
$facturation = $em->getRepository('EcommerceBundle:UtilisateursAdresses')->find($adresse['facturation']);
return $this->render('EcommerceBundle:Default/panier/layout:validation.html.twig',array(
'produits' => $produits,
'livraison'=> $livraison,
'facturation'=>$facturation,
'panier'=>$session->get('panier')
));
}
Confirm that you have initialized your variable $adresse as an array before using it, like below:
$adresse = array();

OneupUploaderBundle and jQuery-File-Upload on symfony 2

I've been trying this but I'm confused since I'm new to Symfony Events and stuff.
This is where I've got so far:
composer bundle installation
AppKernel.php, routing.yml, services.yml, config.yml, UploadListener.php file modifications
And it works, the file I put is actually being uploaded to the folder, and I got the status bar filling... but I need something else:
somehow I need to post (and read) an item id (integer) along with the file (or to be able to set the filename when the file is being copied to the output folder)
if something goes wrong with the upload, how do I send an error message back?
In the example (jQuery-File-Uploader), the code returns the filename of the file that was uploaded, my code doesn't do that, I mean the code is there, but it doesn't work
I'm posting the code I have.
HTML code (here is the piece where I call the jQuery-File-Upload
<tr>
<td>{{ clienteCorporativo.nombreComercial|upper }}</td>
<td>{% if clienteCorporativo.afiliadosUploads|length == 0 %}Nunca{% else %}{{ (clienteCorporativo.afiliadosUploads|last).fecha|date('d/mmm/y') }}{% endif %}</td>
<td>
{% if clienteCorporativo.formatoExcelAfiliados == null %}
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-upload"></i>
<span>Seleccionar Excel</span>
<input id="fileupload_{{ clienteCorporativo.id }}" class="fileupload" data-id="{{ clienteCorporativo.id }}" type="file" name="files[]" multiple>
</span>
{#<span style="color: #8c8c8c"><span class="glyphicon glyphicon-upload"></span> Seleccionar Excel </span>#}
{% else %}
<input id="fileupload_{{ clienteCorporativo.id }}" class="fileupload" type="file" name="files[]" data-url="{{ oneup_uploader_endpoint('gallery') }}" />
{#<a role="button" data-toggle="modal" data-target="#myModal" data-operation="loadOne" data-id="{{ clienteCorporativo.id }}"><span class="glyphicon glyphicon-upload"></span> Seleccionar Excel</a> #}
{% endif %}
<a role="button" data-toggle="modal" data-target="#myModal" data-operation="defineFormat" data-id="{{ clienteCorporativo.id }}"><span class="glyphicon glyphicon-list-alt"></span> Definir Formato</a>
{% if clienteCorporativo.afiliadosUploads|length == 0 %}
<span style="color: #8c8c8c"><span class="glyphicon glyphicon-repeat"></span> Revertir Última Carga </span>
{% else %}
<a role="button" data-toggle="modal" data-target="#myModal" data-operation="undoLast" data-id="{{ clienteCorporativo.id }}"><span class="glyphicon glyphicon-repeat"></span> Revertir Última Carga</a>
{% endif %}
</td>
<td>
<div id="progress_{{ clienteCorporativo.id }}" class="progress text-center">
<div class="progress-bar progress-bar-success">
<span id="files_{{ clienteCorporativo.id }}"></span>
</div>
</div>
</td>
</tr>
js script (the "each" sentence does nothing)
<script>
/*jslint unparam: true */
/*global window, $ */
var idFile = 0;
$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
$('.fileupload').fileupload({
url: '{{ oneup_uploader_endpoint('xlsfile') }}',
dataType: 'json',
done: function (e, data) {
var eventTrigger = $(this)
idFile = eventTrigger.data('id')
$.each(data.result.files, function (index, file) {
$('#files_'+idFile).html(file.name);
});
},
progressall: function (e, data) {
var eventTrigger = $(this)
idFile = eventTrigger.data('id')
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress_'+idFile+' .progress-bar').css(
'width',
progress + '%'
);
},
formData: [ {"id":idFile} ]
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
//
});
</script>
The other files (AppKernel.php, routing.yml, services.yml, config.yml, UploadListener.php) are just like the OneupUploaderBundle documentation says (I've changed things and then rolled back since I didn't got the results I expected). I think I chew more that I could swallow on this one...
Your form fields will be posted with the file upload. Or you can use the form_data: {} option in your $('#myFile').fileUploader() constructor. But it will submit your form fields by default and you can handle those in the usual way.
$('#myFile').fileupload({
dataType: 'json',
formData: {
'file_id': 1
},
You have to craft your own return response in your UploadListener. Then parse the results on the front-end (Javascript).
$response = $event->getResponse();
$response['success'] = true;
$response['files'] = [
'file' => [
'name' => $event->getFile()->getPathname()
]
];
return $response;

Resources