I have problem with configure blueimp. When I send file (click: start upload) in jsconsole is:
POST XXXapp_dev.php/_uploader/gallery/upload 500 (Internal Server
Error)
I used:
Simple example of the entity file to be uploaded with OneupUploaderBundle
https://github.com/1up-lab/OneupUploaderBundle/issues/51#issuecomment-24878715
My file:
services.yml:
Cms.upload_listener:
class: Cms\AdminBundle\EventListener\UploadListener
arguments: [#doctrine]
tags:
- { name: kernel.event_listener, event: oneup_uploader.post_upload, method: onUpload }
config.yml:
oneup_uploader:
mappings:
gallery:
frontend: blueimp
storage:
service: ~
type: filesystem
filesystem: ~
directory: web/uploads/gallery
stream_wrapper: ~
sync_buffer_size: 100K
routing.yml
oneup_uploader:
resource: .
type: uploader
~Entity/File.php
/* ... */
/**
* #ORM\Entity
* #ORM\Table(name="file")
*/
class file {
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string")
*/
protected $filename;
}
~/EventListner/UploadListner.php
class UploadListener
{
protected $manager;
public function __construct(EntityManager $manager)
{
$this->manager = $manager;
}
public function onUpload(PostPersistEvent $event)
{
$file = $event->getFile();
$object = new file();
$object->setFilename($file->getPathName());
$this->manager->persist($object);
$this->manager->flush();
}
}
debug route:
_uploader_upload_gallery POST ANY ANY
/_uploader/gallery/upload
Directory /web/uploads/gallery is on the server.
What am I trying to achieve? I need upload files to server and add record to db.
I think that config is incorrect, but where?
Edit 1:
Maybe help
INFO - An exception was thrown while getting the uncalled listeners
(Catchable Fatal Error: Argument 1 passed to
Cms\AdminBundle\EventListener\UploadListener::__construct() must be an
instance of Cms\AdminBundle\EventListener\EntityManager, instance of
Doctrine\Bundle\DoctrineBundle\Registry given, called in
/home/cms/public_html/app/cache/dev/appDevDebugProjectContainer.php on
line 455 and defined) Context:
{"exception":"Object(Symfony\Component\Debug\Exception\ContextErrorException)"}
CRITICAL - Uncaught PHP Exception
Symfony\Component\HttpFoundation\File\Exception\FileException: "Unable
to create the "/uploads/gallery" directory" at
/home/cms/public_html/vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/File/File.php
line 134 Context:
{"exception":"Object(Symfony\Component\HttpFoundation\File\Exception\FileException)"}
I created uploads/gallery! chmod 777. I don't understand.
Edit 2:
Cms.upload_listener:
class: Cms\AdminBundle\EventListener\UploadListener
arguments: ["#doctrine.orm.entity_manager"]
tags:
- { name: kernel.event_listener, event: oneup_uploader.post_upload, method: onUpload }
and:
directory: ./uploads/gallery
Now created, uploaded file in "uploads/gallery/..."
But...
CRITICAL - Uncaught PHP Exception
Symfony\Component\Debug\Exception\ContextErrorException: "Catchable
Fatal Error: Argument 1 passed to
Cms\AdminBundle\EventListener\UploadListener::onUpload() must be an
instance of Oneup\UploaderBundle\Event\PostPersistEvent, instance of
Oneup\UploaderBundle\Event\PostUploadEvent given" at
/home/cms/public_html/src/Cms/AdminBundle/EventListener/UploadListener.php
line 17 Context:
{"exception":"Object(Symfony\Component\Debug\Exception\ContextErrorException)"}
Returns blueimp "Internal Server Error ..." and doesn't add records in the Entity.
Related
let's say I have 3 databases:
prefix_db1
prefix_db2
prefix_db3
And I want to connect to them dynamically from the url like this http://localhost/my-project/web/app_dev.php/db1/books so I know which database to conenct to from the url (in this case prefix_db1)
And basically the idea was to prepare a listener that will be fired with each http request, get the database name from the url and then override doctrin's params, something like this:
Within services.yml:
dynamic_connection:
class: AppBundle\service\DynamicDBConnector
arguments: ['#request_stack']
calls:
- [ setDoctrineConnection, ['#doctrine.dbal.default_connection'] ]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
My listener:
<?php
namespace AppBundle\service;
use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\RequestStack;
use Exception;
class DynamicDBConnector
{
/**
* #var Connection
*/
private $connection;
/*
* #var Request
*/
private $request;
public function __construct(RequestStack $requestStack)
{
$this->request = $requestStack->getCurrentRequest();
}
/**
* Sets the DB Name prefix to use when selecting the database to connect to
*
* #param Connection $connection
* #return DynamicDBConnector $this
*/
public function setDoctrineConnection(Connection $connection)
{
$this->connection = $connection;
return $this;
}
public function onKernelRequest()
{
if ($this->request->attributes->has('_company')) {
$connection = $this->connection;
$params = $this->connection->getParams();
$companyName = $this->request->get('_company');
// I did the concatenation here because in paramaters.yml I just put the prefix (database_name: prefix_) so after the concatenation I get the whole database name "prefix_db1"
$params['dbname'] = $params['dbname'] . $companyName;
// Set up the parameters for the parent
$connection->__construct(
$params,
$connection->getDriver(),
$connection->getConfiguration(),
$connection->getEventManager()
);
try {
$connection->connect();
} catch (Exception $e) {
// log and handle exception
}
}
return $this;
}
}
Now this worked very well I have tested it using a simple list of books and each time I change the url I get the list related to each database:
http://localhost/my-project/web/app_dev.php/db1/books // I get books of database prefix_db1
http://localhost/my-project/web/app_dev.php/db2/books // I get books of database prefix_db2
Now let's get to the problem shall we :):
The problem now is that when I secure my project with authentication system and try to login (of course each database has user table) using this url http://localhost/my-project/web/app_dev.php/db1/login
I get this exception :
An exception occured in driver: SQLSTATE[HY000] [1049] Base 'prefix_' unknown
As you can see symfony tried to login the user using the database_name declared in parameters.yml which means that the security_checker of symfony has been fired before my listener and before overriding Doctrine's params.
My question:
Is there any way to fire my listener before any other http request listener ? or maybe an alternative solution to make sure that any request to database must be with the right database name.
Sorry for the long post.
EDIT:
From the official documentation of symfony:
https://symfony.com/doc/2.3/cookbook/event_dispatcher/event_listener.html
The other optional tag attribute is called priority, which defaults
to 0 and it controls the order in which listeners are executed (the
highest the priority, the earlier a listener is executed). This is
useful when you need to guarantee that one listener is executed before
another. The priorities of the internal Symfony listeners usually
range from -255 to 255 but your own listeners can use any positive or
negative integer.
I set the priority of my listener to 10000:
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 10000 }
But the problem persist, still can't fire my listener before symfony!
I found a solution
The idea is tochange the default Connection class that symfony uses to create a database connection:
doctrine:
dbal:
connections:
default:
wrapper_class: AppBundle\Doctrine\DynamicConnection
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: UTF8
After that we can change the given params in the constructor:
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
class DynamicConnection extends Connection
{
public function __construct(array $params, Driver $driver, $config, $eventManager)
{
$params['dbname'] = 'teqsdqsdqst';
parent::__construct($params, $driver, $config, $eventManager);
}
}
Now we just need to get the parameter from the url and set inside $params['dbname'].
In this way we make sure that symfony will always use this class to create the connection and we no longer need to fire listeners with http requestes
Great solution but if you want get the parameter _company from the URL you can retrieve the container inside the constructor through the EventManager object passed in parameters and get the current request from it, in fact the container is injected into ContainerAwareEventManager the sub class of EventManager
class DynamicDBConnector extends Connection
{
public function __construct($params, $driver, $config, $eventManager)
{
if(!$this->isConnected()){
// Create default config and event manager if none given (case in command line)
if (!$config) {
$config = new Configuration();
}
if (!$eventManager) {
$eventManager = new EventManager();
}
$refEventManager = new \ReflectionObject($eventManager);
$refContainer = $refEventManager->getProperty('container');
$refContainer->setAccessible('public'); //We have to change it for a moment
/*
* #var \Symfony\Component\DependencyInjection\ContainerInterface $container
*/
$conrainer = $refContainer->getValue($eventManager);
/*
* #var Symfony\Component\HttpFoundation\Request
*/
$request = $conrainer->get('request_stack')->getCurrentRequest();
if ($request != null && $request->attributes->has('_company')) {
$params['dbname'] .= $request->attributes->get('_company');
}
$refContainer->setAccessible('private'); //We put in private again
parent::__construct($params, $driver, $config, $eventManager);
}
}
}
you should add the database name in your config.yml like this :
orm:
auto_generate_proxy_classes: '%kernel.debug%'
# naming_strategy: doctrine.orm.naming_strategy.underscore
# auto_mapping: true
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
DataMiningBundle: ~
AppBundle: ~
UserBundle: ~
your_second_db:
connection: your_second_db (decalared in parameters.yml)
mappings:
yourBundle: ~
and call it from your controller :
$em = $doctrine->getConnection('your_second_db');
I'm using FMElfinder in association with TinyMCE for managing the assets (images, pdf ...) of the users (managed with FOSUSerBundle)
I've seen that this tool can handle multiple root folder, but in my case, it isn't quite usable : i would like to have a root folder for each user.
In the configuration file app/config/config.yml, there is the root path(s) defined :
fm_elfinder:
instances:
default:
locale: %locale%
...
connector:
roots:
uploads:
driver: LocalFileSystem
path: uploads/data
I was thining about "simply" changing the path to something like :
path: uploads/data/{the_username}
where the username would be the username of the currently logged user
In a controller i can do
$user = $this->get('security.token_storage')->getToken()->getUser();
$username = $user->getUsername();
But i don't know if it's possible (and if so, how) to access specifically the username of the logged user into a config file
Thank you if you have any suggestion
=================[EDIT] ==========================================
I've use the override of configuration. I think i followed the steps, but i haven't managed to make it work :
1 - Create the class
use FM\ElfinderBundle\Model\ElFinderConfigurationProviderInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ElfinderConfigurator implements ElFinderConfigurationProviderInterface
{
protected $container;
protected $options;
/**
* #param ContainerInterface $container
*/
public function __construct($options, ContainerInterface $container)
{
$this->container = $container;
$this->storage = $container->get('security.token_storage');
$this->options = $options;
}
/**
* #param $instance
*
* #return array
*/
public function getConfiguration($instance)
{
//retrieve basepath
$basepath_abs = $this->container->get('kernel')->getRootDir()."/../web/uploads";
$basepath = "uploads/data";
//define path for user
$userid = $this->storage->getToken()->getUser()->getId();
$root = $basepath.'/'.$userid;
$this->options['instances']['default']['connector']['roots']['uploads']['path'] = $root.'/root';
$this->options['instances']['default']['connector']['roots']['uploads']['upload_max_size'] = '2M';
$option = [
'corsSupport' => false,
'roots' => $this->options['instances']['default']['connector']['roots'],
];
$root_abs = $basepath_abs.'/data/'.$userid;
//creates dir if not available
if (!is_dir($root_abs)) {
mkdir($root_abs.'/root', 0775, true);
}
return $option;
}
}
2 - Set my service :
myvendor.mybundle.elfinder_configurator:
class: Myvendor\Mybundle\Services\ElfinderConfigurator
arguments: ["%fm_elfinder%", "#service_container"]
3 - Call the service in app/config/config.yml
fm_elfinder:
configuration_provider: myvendor.mybundle.elfinder_configurator
...
It works partially : When i open the elfinde, the directory are correctly created if they don't exists. But there must be a path problem, and i'm not sure it's well overriden because :
- The thumbs are not displayed in elfinder
- When i add the image to the editor, i don't have the correct path of the image, i have :
//app_dev.php/efconnect?cmd=file&target=l1_Q2FwdHVyZSBkJ8OpY3JhbiBkZSAyMDE2LTAxLTI0IDE0OjM2OjI0LnBuZw
instead of the actual path of the image (if i don't use the override, the tool works and gives me this path)
../../../../uploads/data/1/root/img1.png
and no image is displayed.
Also, if i look in the js console for the
efconnect?cmd=open&target=&init=1&tree=1&_=1469377765664
I see that uplMaxSize is 200M,
in any case, there is no js error in the console
I think you are looking for a custom config provider:
https://github.com/helios-ag/FMElfinderBundle/blob/master/Resources/doc/advanced-configuration.md#custom-configuration-provider
You could then inject the token storage into the service and fetch the user from
like in any controller:
services:
my_elfinder_configurator:
class: Acme\DemoBundle\elFinder\UserAwareConfigurator
arguments: ["#token_storage", "%any_container_params%"]
I'm trying to upload one or more files using OneupUploaderBundle but I can not get it to work since files aren't uploaded and nothing is persisted to DB. I'll explain what I've done til now:
config.yml:
oneup_uploader:
mappings:
recaudos:
frontend: blueimp
storage:
service: ~
type: filesystem
filesystem: ~
directory: %kernel.root_dir%/../web/uploads/recaudos
stream_wrapper: ~
sync_buffer_size: 100K
allowed_mimetypes: [application/msword,image/jpeg,image/pjpeg,image/png,application/pdf,application/vnd.oasis.opendocument.text]
#disallowed_mimetypes: []
error_handler: oneup_uploader.error_handler.noop
# Set max_size to -1 for gracefully downgrade this number to the systems max upload size.
#max_size: 9223372036854775807
use_orphanage: true
enable_progress: true
enable_cancelation: true
namer: oneup_uploader.namer.uniqid
At Twig template only this:
<input id="fileUpload3" class="fileUpload" type="file" name="fileUpload3[]" data-url="{{ oneup_uploader_endpoint('recaudos') }}" multiple />
$(document).ready(function(){
$('fileUpload3').fileupload();
});
And latest this is the Listener for onUpload event:
namespace AppBundle\EventListener;
use Oneup\UploaderBundle\Event\PostPersistEvent;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Entity;
class UploadListener
{
protected $doctrine;
public function __construct($doctrine)
{
$this->doctrine = $doctrine;
}
public function onUpload(PostPersistEvent $event, Request $request)
{
$session = $request->getSession();
$em = $this->doctrine->getManager();
$request = $event->getRequest();
$tempfile = $event->getFile();
$productoSolicitud = $em->getRepository('SolicitudProducto')->find($session->get('productoSolicitudId'));
$recaudosTramiteProductoSolicitud = new Entity\RecaudosTramitesProductoSolicitud();
$recaudosTramiteProductoSolicitud->setProductoSolicitud($productoSolicitud);
$filenamePart = explode("--", $tempfile->getName());
$pathinfo = pathinfo($tempfile->getName());
$recaudosTramiteProductoSolicitud->setArchivo($pathinfo['filename']);
$em->persist($recaudosTramiteProductoSolicitud);
$em->flush();
}
}
And of course I have service defined also:
appbundle.upload_listener:
class: "AppBundle\EventListener\UploadListener"
arguments: [#doctrine]
tags:
- { name: 'kernel.event_listener', event: "oneup_uploader.post_persist", method: "onUpload" }
Did I miss something? Why file are not uploaded and data is not persisted? As you may see in the attached image there is a post request to _uploader/recaudos/upload, any advice?
I just checked my own OneupUploader implementation:
Rename your function "onUpload" to "onPostUpload" and change your service configuration to this:
appbundle.upload_listener:
class: "AppBundle\EventListener\UploadListener"
arguments: [#doctrine]
tags:
- { name: 'kernel.event_listener', event: oneup_uploader.post_upload, method: onPostUpload }
Should work, works for me.
If you need your original file name you also need an onUpload Method and this:
tags:
# - {...
- { name: kernel.event_listener, event: oneup_uploader.pre_upload, method: onUpload }
Regarding your comment:
//UploadListener
class UploadListener
{
protected $originalName;
public function onUpload(PreUploadEvent $event)
{
$file = $event->getFile();
$this->originalName = $file->getClientOriginalName();
}
public function onPostUpload(PostUploadEvent $event)
{
$fileEntity = new YourFileEntity();
$fileEntity->setYourOriginalNameProperty($this->originalName);
//...
}
}
I am trying to create a manual provider to manually populate my FOS Elastica index to account for some complex joins. At the moment, I am just trying to get the provider to work even without the joins, and I am having trouble injecting the correct Elastica Type into my constructor for the provider. Here is the constructor of my provider:
// ...
class EmpPosDeptProvider implements ProviderInterface
{
private $em;
protected $type;
public function __construct(Type $type, EntityManager $em)
{
$this->type = $type;
$this->em = $em->getRepository('CcitEmployeesBundle:Position');
}
// ...
and here is my services.yml file:
services:
employees.search_provider.empPosDept:
class: Ccit\EmployeesBundle\Search\EmpPosDeptProvider
tags:
- { name: fos_elastica.provider, index: employees, type: empPosDept }
arguments:
- %fos_elastica.type.class%
- #doctrine.orm.entity_manager
When I try to execute php app/console fos:elastica:populate I am receiving the following error:
PHP Catchable fatal error: Argument 1 passed to Ccit\EmployeesBundle\Search
\EmpPosDeptProvider::__construct() must be an instance of Elastica\Type, string given,
called in /vagrant-nfs/employees/app/cache/dev/appDevDebugProjectContainer.php on line 736
and defined in /vagrant-nfs/employees/src/Ccit/EmployeesBundle/Search
/EmpPosDeptProvider.php on line 23
Does anyone know what I need to give as a correct argument in my services.yml file? Or could the problem be something else entirely?
You're passing a string containing Ccit\EmployeesBundle\Search\EmpPosDeptProvider. You have to pass an instance of EmpPosDeptProvider, and it may be declared in your services.yml something like:
services:
fos_elastica.type:
class: %fos_elastica.type.class%
employees.search_provider.empPosDept:
class: Ccit\EmployeesBundle\Search\EmpPosDeptProvider
tags:
- { name: fos_elastica.provider, index: employees, type: empPosDept }
arguments:
- #fos_elastica.type
- #doctrine.orm.entity_manager
Apparently I needed to provide the explicit path to the type I was referencing. The following line worked:
#fos_elastica.index.employees.employeePositionDepartment
This makes sense given that my config.yml file contains the following:
fos_elastica:
clients:
default: { host: localhost, port: 9200 }
indexes:
employees:
client: default
types:
employeePositionDepartment:
mappings:
id: { type: integer }
title: { type: string }
startDate: { type: date, format: date_time_no_millis }
endDate: { type: date, format: date_time_no_millis }
supervisor: { type: integer }
Thanks to anyone who was considering helping me with this rather elementary question.
In an attempt to combine Monolog e-mailing errors with a custom exception handler I get the following:
[Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException]
Circular reference detected for service "router", path: "router ->
monolog.logger.router -> monolog.handler.grouped ->
mana.exception.listener -> templating -> twig ->
templating.helper.logout_url".
I make no claims to really know what I'm doing here, as evidenced by all the errors.
Services excerpt:
mana.exception.listener:
class: Mana\ClientBundle\EventListener\ExceptionListener
arguments: [#templating, #kernel]
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
Config excerpt:
monolog:
handlers:
main:
type: stream
path: %kernel.logs_dir%/%kernel.environment%.log
level: debug
handler: grouped
grouped:
type: group
members: [mail, custom]
mail:
type: fingers_crossed
action_level: error
handler: buffered
buffered:
type: buffer
handler: swift
swift:
type: swift_mailer
from_email: error#projectmana.org
to_email: truckeetrout#yahoo.com
subject: An Error Occurred!
level: debug
custom:
type: service
id: mana.exception.listener
Custom handler:
class ExceptionListener {
protected $templating;
protected $kernel;
public function __construct(EngineInterface $templating, $kernel) {
$this->templating = $templating;
$this->kernel = $kernel;
}
public function onKernelException(GetResponseForExceptionEvent $event) {
// provide the better way to display a enhanced error page only in prod environment, if you want
if ('prod' == $this->kernel->getEnvironment()) {
// exception object
$exception = $event->getException();
// new Response object
$response = new Response();
// set response content
$response->setContent(
// create you custom template AcmeFooBundle:Exception:exception.html.twig
$this->templating->render(
'ManaClientBundle:Exception:exception.html.twig', array('exception' => $exception)
)
);
// HttpExceptionInterface is a special type of exception
// that holds status code and header details
if ($exception instanceof HttpExceptionInterface) {
$response->setStatusCode($exception->getStatusCode());
$response->headers->replace($exception->getHeaders());
} else {
$response->setStatusCode(500);
}
// set the new $response object to the $event
$event->setResponse($response);
}
}
It's your Exception Listener. Delete #kernel from the arguments array and you're fine
mana.exception.listener:
class: Mana\ClientBundle\EventListener\ExceptionListener
arguments: [#templating]
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }
Your custom exception listener probably depends on monolog either in the templating or kernel service.