Create new block in Sonata Admin Bundle causes an error - php

I refer this solution https://stackoverflow.com/a/15167450/2910183 ,and an error occur:
Compile Error: Declaration of
AppBundle\Block\NewsletterBlockService::execute() must be compatible
with
Sonata\BlockBundle\Block\BlockServiceInterface::execute(Sonata\BlockBundle\Block\BlockContextInterface
$blockContext, Symfony\Component\HttpFoundation\Response $response =
NULL)
Code
Part of my app/config/config.yml
sonata_block:
default_contexts: [cms]
blocks:
# enable the SonataAdminBundle block
sonata.admin.block.admin_list:
contexts: [admin]
sonata.user.block.menu: ~ # used to display the menu in profile pages
sonata.user.block.account: ~ # used to display menu option (login option)
sonata.block.service.text: ~
sonata.block.service.rss: ~
sonata.block.service.newsletter: ~
sonata_admin:
dashboard:
blocks:
-
position: left
type: sonata.admin.block.admin_list
settings:
groups: [default, app.admin.group.content]
-
position: right
type: sonata.admin.block.admin_list
settings:
groups: [default]
- { position: left, type: sonata.block.service.newsletter}
Part of my /private/var/www/learning_sonata/app/config/services.yml
sonata.block.service.newsletter:
class: AppBundle\Block\NewsletterBlockService
arguments: [ "sonata.block.service.newsletter", #templating ]
tags:
- { name: sonata.block }
My /private/var/www/learning_sonata/src/AppBundle/Block/NewsletterBlockService.php
namespace AppBundle\Block;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Block\BlockContext;
use Sonata\BlockBundle\Block\BlockServiceInterface;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\CoreBundle\Validator\ErrorElement;
use Sonata\BlockBundle\Block\BaseBlockService;
//use Sonata\BlockBundle\Block;
class NewsletterBlockService extends BaseBlockService
{
public function getName()
{
return 'My Newsletter';
}
public function getDefaultSettings()
{
return array();
}
public function validateBlock(ErrorElement $errorElement, BlockInterface $block)
{
}
public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
{
}
public function execute(BlockInterface $block, Response $response = null)
{
// merge settings
$settings = array_merge($this->getDefaultSettings(), $block->getSettings());
return $this->renderResponse('InstitutoStoricoNewsletterBundle:Block:block_my_newsletter.html.twig', array(
'block' => $block,
'settings' => $settings
), $response);
}
}
Thanks devilcius!
I refer your answer,clear the error above,but new erro occur:
Method "id" for object "Sonata\BlockBundle\Block\BlockContext" does
not exist in SonataBlockBundle:Block:block_base.html.twig at line 11
File path vendor/sonata-project/block-bundle/Resources/views/Block/block_base.html.twig
<div id="cms-block-{{ block.id }}" class="cms-block cms-block-element">
{% block block %}EMPTY CONTENT{% endblock %}
</div>
Sonata Version
sonata-project/admin-bundle 3.1.0 The missing Symfony Admin ...
sonata-project/block-bundle 3.0.0 Symfony SonataBlockBundle
sonata-project/cache 1.0.7 Cache library
sonata-project/core-bundle 3.0.0 Symfony SonataCoreBundle
sonata-project/doctrine-orm-admin-bundle 3.0.1 Symfony Sonata / Integrate...
sonata-project/exporter 1.4.1 Lightweight Exporter library
I read this resource,it said it's the version pro.
Could u give some idea,guys?

You're not implementing the method signature when extending BaseBlockService.
use Sonata\BlockBundle\Block\BlockContextInterface;
public function execute(BlockContextInterface $blockContext, Response $response = null)
{
return $this->renderResponse('InstitutoStoricoNewsletterBundle:Block:block_my_newsletter.html.twig', array(
'block' => $blockContext->getBlock(),
'settings' => $blockContext->getSettings()
), $response);
}

Related

validation.yml file is ignored

I'm new to symfony, and I'm currently trying to understand Symfony3.
While validation through annotations works fine, I can't activate validation through validation.yml file.
In my app/config/config.yml, I changed this line :
framework:
validation: { enabled: true, enable_annotations: false }
My src/AppBundle/Resources/config/validation.yml is :
# src/AppBundle/Resources/config/validation.yml
AppBundle\Entity\TaskSetClass:
properties:
taskName:
- NotBlank: ~
dueDate:
- NotBlank: ~
- Type: \DateTime
I added a extension file :
<?php
// src/AppBundle/DependencyInjection/AppExtension.php
namespace AppBundle\DependencyInjection;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Finder\Finder;
/* */
class AppExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$container=new ContainerBuilder();
// Services
$loader=new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../../../app/config'));
$loader->load('services.yml');
// Validation
// Commented : No "validator.mapping.loader.yaml_files_loader.mapping_files" parameter.
//$yamlMappingFiles=$container->getParameter('validator.mapping.loader.yaml_files_loader.mapping_files');
$finder=new Finder();
foreach($finder->files()->in(__DIR__.'/../../../app/Resources/config') as $file)
{
$filePath=$file->getRealPath();
if(preg_match('#\.yml$#',$filePath)===1)
{
$yamlMappingFiles[]=$filePath;
}
}
$container->setParameter('validator.mapping.loader.yaml_files_loader.mapping_files', $yamlMappingFiles);
}
}
A dump of the container after the setParameter() in appExtension.php shows the command has succeeded :
[parameterBag:protected] => Symfony\Component\DependencyInjection\ParameterBag\ParameterBag Object
(
[parameters:protected] => Array
(
[validator.mapping.loader.yaml_files_loader.mapping_files] => Array
(
[0] => /mnt/400Go/www/sy1/app/Resources/config/validation.yml
)
)
[resolved:protected] =>
)
In my form controller, if I list the constraints :
[...]
if($form->isSubmitted())
{
if($form->isValid())
{
$metadata=$this->container
->get('validator')
->getMetadataFor('AppBundle\Entity\TaskSetClass');
$propertiesMetadata=$metadata->properties;
$constraints=array();
foreach ($propertiesMetadata as $propertyMetadata)
{
$constraints[$propertyMetadata->name]=$property->constraints;
}
echo'<pre>Constraints : ';
print_r($constraints);
echo'</pre>';
die();
[...]
... the array is empty. so the file seems to be loaded, but the constraints are ignored.
Did anyone encountered this error? It may comes from a difference between symfony 2 and 3.
[SOLVED] The validation file was not in the correct directory. It was supposed to be in AppBundle/Resources/config and I had it into app/Resouces/config. Works fine now.

Symfony 3 Redirect All Routes To Current Locale Version

I am working on a symfony application where my goal is no matter what page the user is on it will navigate to the locale version of the page.
For example, if the user navigates to "/" the home page, it will redirect to "/en/"
If they are on "/admin" page it will redirect to "/en/admin", in such a way that the _locale property is set from the route.
Also it needs to determine the locale if they visit /admin from the users browser since no locale was determined so it knows which page to redirect to.
Currently my default controller looks like below since I'm testing. I'm using the dev mode & profiler to test that translations are working in correct.
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
* #Route("/", name="homepage")
* #Route("/{_locale}/", name="homepage_locale")
*/
public function indexAction(Request $request)
{
$translated = $this->get('translator')->trans('Symfony is great');
// replace this example code with whatever you need
return $this->render('default/index.html.twig', [
'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
'translated' => $translated
]);
}
}
This current method will keep the user at "/" if they navigate there, but I want to have it redirect to "/en/". This should work for other pages too, like /admin, or /somepath/pathagain/article1 (/en/admin , /en/somepath/pathagain/article1)
How would I do this?
References I've read that did not help:
Symfony2 Use default locale in routing (one URL for one language)
Symfony2 default locale in routing
::Update::
I have not solved my issue but I've come close as well as learned a few tricks to be more efficient.
DefaultController.php
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
* #Route("/", name="home", defaults={"_locale"="en"}, requirements={"_locale" = "%app.locales%"})
* #Route("/{_locale}/", name="home_locale", requirements={"_locale" = "%app.locales%"})
*/
public function indexAction(Request $request)
{
$translated = $this->get('translator')->trans('Symfony is great');
// replace this example code with whatever you need
return $this->render('default/index.html.twig', [
'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
'translated' => $translated
]);
}
/**
* #Route("/admin", name="admin", defaults={"_locale"="en"}, requirements={"_locale" = "%app.locales%"})
* #Route("/{_locale}/admin", name="admin_locale", requirements={"_locale" = "%app.locales%"})
*/
public function adminAction(Request $request)
{
$translated = $this->get('translator')->trans('Symfony is great');
// replace this example code with whatever you need
return $this->render('default/index.html.twig', [
'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
'translated' => $translated
]);
}
}
?>
Config.yml
imports:
- { resource: parameters.yml }
- { resource: security.yml }
- { resource: services.yml }
# Put parameters here that don't need to change on each machine where the app is deployed
# http://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: en
app.locales: en|es|zh
framework:
#esi: ~
translator: { fallbacks: ["%locale%"] }
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form: ~
csrf_protection: ~
validation: { enable_annotations: true }
#serializer: { enable_annotations: true }
templating:
engines: ['twig']
#assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
# handler_id set to null will use default session handler from php.ini
handler_id: ~
save_path: "%kernel.root_dir%/../var/sessions/%kernel.environment%"
fragments: ~
http_method_override: true
assets: ~
# Twig Configuration
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
# Doctrine Configuration
doctrine:
dbal:
driver: pdo_mysql
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
# if using pdo_sqlite as your database driver:
# 1. add the path in parameters.yml
# e.g. database_path: "%kernel.root_dir%/data/data.db3"
# 2. Uncomment database_path in parameters.yml.dist
# 3. Uncomment next line:
# path: "%database_path%"
orm:
auto_generate_proxy_classes: "%kernel.debug%"
naming_strategy: doctrine.orm.naming_strategy.underscore
auto_mapping: true
# Swiftmailer Configuration
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool: { type: memory }
Notice under parameters the value app.locales: en|es|zh. This is now a value I can reference whenever I create my routes if I plan to support more locales in the future which I do. Those routes are english, spanish, chinese in that order for those curious. In the DefaultController in the annotations the "%app.locales%" is the part that references the config parameter.
The problem with my current method is going to /admin for example does not redirect the user to /{browsers locale}/admin, which would be the more elegant solution to keep everything organized... but at least the routes work. Still looking for better solution.
****Update****
I think I may have possibly found the answer here as the bottom answer given (Add locale and requirements to all routes - Symfony2), the answer by Athlan. Just not sure how to implement this in symfony 3 as his directions were not clear enough to me.
I think this article might help also (http://symfony.com/doc/current/components/event_dispatcher/introduction.html)
I don't have enough reputation to add a comment to the correct solution. So I'm adding a new answer
You can add "prefix: /{_locale}" at app/config/routing.yml like this:
app:
resource: "#AppBundle/Controller/"
type: annotation
prefix: /{_locale}
So you don't need to add it to every route to every action. For the following steps. Thank you very much it's perfect.
After 12 hours of looking into this I finally found an acceptable solution. Please post revised versions of this solution if you can make it more efficient.
Some things to note, my solution is particular to my need. What it does is force any URL to go to a localized version if it exists.
This requires some conventions to be followed when you create routes.
DefaultController.php
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
* #Route("/{_locale}/", name="home_locale", requirements={"_locale" = "%app.locales%"})
*/
public function indexAction(Request $request)
{
$translated = $this->get('translator')->trans('Symfony is great');
// replace this example code with whatever you need
return $this->render('default/index.html.twig', [
'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
'translated' => $translated
]);
}
/**
* #Route("/{_locale}/admin", name="admin_locale", requirements={"_locale" = "%app.locales%"})
*/
public function adminAction(Request $request)
{
$translated = $this->get('translator')->trans('Symfony is great');
// replace this example code with whatever you need
return $this->render('default/index.html.twig', [
'base_dir' => realpath($this->container->getParameter('kernel.root_dir').'/..'),
'translated' => $translated
]);
}
}
?>
Notice that both routes always start with "/{_locale}/". For this to work every route in your project needs to have this. You just put the real route name afterwards. For me I was okay with this scenario. You can modify my solution to fit your needs easily enough.
The first step is to create a listen on the httpKernal to intercept requests before they go to the routers to render them.
LocaleRewriteListener.php
<?php
//src/AppBundle/EventListener/LocaleRewriteListener.php
namespace AppBundle\EventListener;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Routing\RouteCollection;
class LocaleRewriteListener implements EventSubscriberInterface
{
/**
* #var Symfony\Component\Routing\RouterInterface
*/
private $router;
/**
* #var routeCollection \Symfony\Component\Routing\RouteCollection
*/
private $routeCollection;
/**
* #var string
*/
private $defaultLocale;
/**
* #var array
*/
private $supportedLocales;
/**
* #var string
*/
private $localeRouteParam;
public function __construct(RouterInterface $router, $defaultLocale = 'en', array $supportedLocales = array('en'), $localeRouteParam = '_locale')
{
$this->router = $router;
$this->routeCollection = $router->getRouteCollection();
$this->defaultLocale = $defaultLocale;
$this->supportedLocales = $supportedLocales;
$this->localeRouteParam = $localeRouteParam;
}
public function isLocaleSupported($locale)
{
return in_array($locale, $this->supportedLocales);
}
public function onKernelRequest(GetResponseEvent $event)
{
//GOAL:
// Redirect all incoming requests to their /locale/route equivlent as long as the route will exists when we do so.
// Do nothing if it already has /locale/ in the route to prevent redirect loops
$request = $event->getRequest();
$path = $request->getPathInfo();
$route_exists = false; //by default assume route does not exist.
foreach($this->routeCollection as $routeObject){
$routePath = $routeObject->getPath();
if($routePath == "/{_locale}".$path){
$route_exists = true;
break;
}
}
//If the route does indeed exist then lets redirect there.
if($route_exists == true){
//Get the locale from the users browser.
$locale = $request->getPreferredLanguage();
//If no locale from browser or locale not in list of known locales supported then set to defaultLocale set in config.yml
if($locale=="" || $this->isLocaleSupported($locale)==false){
$locale = $request->getDefaultLocale();
}
$event->setResponse(new RedirectResponse("/".$locale.$path));
}
//Otherwise do nothing and continue on~
}
public static function getSubscribedEvents()
{
return array(
// must be registered before the default Locale listener
KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
);
}
}
Finally you set the services.yml to start the listener up.
Services.yml
# Learn more about services, parameters and containers at
# http://symfony.com/doc/current/book/service_container.html
parameters:
# parameter_name: value
services:
# service_name:
# class: AppBundle\Directory\ClassName
# arguments: ["#another_service_name", "plain_value", "%parameter_name%"]
appBundle.eventListeners.localeRewriteListener:
class: AppBundle\EventListener\LocaleRewriteListener
arguments: ["#router", "%kernel.default_locale%", "%locale_supported%"]
tags:
- { name: kernel.event_subscriber }
Also in the config.yml you will want to add the following under parameters:
config.yml
parameters:
locale: en
app.locales: en|es|zh
locale_supported: ['en','es','zh']
I wanted there to be only one place you define the locales but I wound up having to do 2...but at least they are in the same spot so easy to change.
app.locales is used in default controller (requirements={"_locale" = "%app.locales%"}) and locale_supported is used in the LocaleRewriteListener. If it detects a locale that is not in the list it will fallback to the default locale, which in this case is the value of locale:en.
app.locales is nice with the requirements command because it will cause a 404 for any locales that do not match.
If you are using forms and have a login you will need to do the following to your security.yml
Security.yml
# To get started with security, check out the documentation:
# http://symfony.com/doc/current/book/security.html
security:
encoders:
Symfony\Component\Security\Core\User\User:
algorithm: bcrypt
cost: 12
AppBundle\Entity\User:
algorithm: bcrypt
cost: 12
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
# http://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
database:
entity: { class: AppBundle:User }
#property: username
# if you're using multiple entity managers
# manager_name: customer
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
form_login:
check_path: login_check
login_path: login_route
provider: database
csrf_token_generator: security.csrf.token_manager
remember_me:
secret: '%secret%'
lifetime: 604800 # 1 week in seconds
path: /
httponly: false
#httponly false does make this vulnerable in XSS attack, but I will make sure that is not possible.
logout:
path: /logout
target: /
access_control:
# require ROLE_ADMIN for /admin*
#- { path: ^/login, roles: ROLE_ADMIN }
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/(.*?)/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
The important change to note here is that (.*?)/login will authenticate anonymously so your users can still login. This does mean that routes like..dogdoghere/login could trigger, but the requirements I will show you shortly on the login routes prevent this and will throw 404 errors. I like this solution with the (.*?) versus [a-z]{2} incase you wanted to use en_US type locales.
SecurityController.php
<?php
// src/AppBundle/Controller/SecurityController.php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class SecurityController extends Controller
{
/**
* #Route("{_locale}/login", name="login_route", defaults={"_locale"="en"}, requirements={"_locale" = "%app.locales%"})
*/
public function loginAction(Request $request)
{
$authenticationUtils = $this->get('security.authentication_utils');
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render(
'security/login.html.twig',
array(
// last username entered by the user
'last_username' => $lastUsername,
'error' => $error,
)
);
}
/**
* #Route("/{_locale}/login_check", name="login_check", defaults={"_locale"="en"}, requirements={"_locale" = "%app.locales%"})
*/
public function loginCheckAction()
{
// this controller will not be executed,
// as the route is handled by the Security system
}
/**
* #Route("/logout", name="logout")
*/
public function logoutAction()
{
}
}
?>
Note that even these paths use {_locale} in front. I like this however so I can give custom logins for different locales. Just keep that in mind. The only route that does not need the locale is logout which works just fine since its really only an intercept route for the security system. Also notice it uses the requirements which is set from the config.yml, so you only have to edit it in one place for all the routes across your projects.
Hope this helps someone trying to do what I was doing!
NOTE:: To test this easily I use 'Quick Language Switcher' extension for Google Chrome, which changes the accept-language header on all requests.
final function smallResumeOfResearching($localeRewrite, $opinion = 'IMHO') :)
The method, provided by mr. Joseph working great with routes like /{route_name}, or /, but not with routes like /article/slug/other.
If we use modified mr.Joseph's method, provided by https://stackoverflow.com/a/37168304/9451542, we will lost profiler and debugger in dev mode.
If we want more flexible solution, onKernelRequest method can be modified like this (thanks to mr. Joseph, thanks to https://stackoverflow.com/a/37168304/9451542):
public function onKernelRequest(GetResponseEvent $event)
{
$pathInfo = $event->getRequest()->getPathinfo();
$baseUrl = $event->getRequest()->getBaseUrl();
$checkLocale = explode('/', ltrim($pathInfo, '/'))[0];
//Or some other logic to detect/provide locale
if (($this->isLocaleSupported($checkLocale) == false) && ($this->defaultLocale !== $checkLocale)) {
if ($this->isProfilerRoute($checkLocale) == false) {
$locale = $this->defaultLocale;
$event->setResponse(new RedirectResponse($baseUrl . '/' . $locale . $pathInfo));
}
/* Or with matcher:
try {
//Try to match the path with the locale prefix
$this->matcher->match('/' . $locale . $pathInfo);
//$event->setResponse(new RedirectResponse($baseUrl . '/' . $locale . $pathInfo));
} catch (\Symfony\Component\Routing\Exception\ResourceNotFoundException $e) {
} catch (\Symfony\Component\Routing\Exception\MethodNotAllowedException $e) {
}
*/
}
}
note: $this->profilerRoutes = array('_profiler', '_wdt', '_error');
Thanks to Susana Santos for pointing to simple config method :)
Small improvement for Symfony 3.4:
Be sure, that the getSubscribedEvents() will register LocaleRewriteListener BEFORE RouterListener::onKernelRequest and BEFORE LocaleListener::onKernelRequest. Integer 17 must be greater than RouterListener::onKernelRequest priotity. Otherwise you will got 404.
bin/console debug:event-dispatcher
Service definition in services.yml must be (depends on Symfony configuration):
AppBundle\EventListener\LocaleRewriteListener:
arguments: ['#router', '%kernel.default_locale%', '%locale_supported%']
tags:
- { name: kernel.event_subscriber, event: kernel.request }

Symfony2 can't find Route on custom Route Loader

I'm having the same problem symfony2 is describing here
This comes in handy when you have a bundle but don't want to manually
add the routes for the bundle to app/config/routing.yml. This may be
especially important when you want to make the bundle reusable
TLDR; im trying to implement a custom Route Loader using this part of the symfony2 documentation
http://symfony.com/doc/current/cookbook/routing/custom_route_loader.html#more-advanced-loaders
However it doesn't seem to be working, the route cannot be found;
This is what I've tried so far:
The loader:
<?php
//namespace Acme\DemoBundle\Routing;
namespace Gabriel\AdminPanelBundle\Routing;
use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Routing\RouteCollection;
class AdvancedLoader extends Loader
{
public function load($resource, $type = null)
{
$collection = new RouteCollection();
$resource = '#GabrielAdminPanelBundle/Resources/config/routing.yml';
$type = 'yaml';
$importedRoutes = $this->import($resource, $type);
$collection->addCollection($importedRoutes);
return $collection;
}
public function supports($resource, $type = null)
{
return $type === 'advanced_extra';
}
}
here is my routing.yml
located in: src/Gabriel/AdminPanelBundle/Resources/config/routing.yml
the routing.yml
gabriel_admin_panel:
resource: "#GabrielAdminPanelBundle/Controller/"
type: annotation
prefix: /superuser
The Routes of the bundle can't be found unless I put the Routes back in the main app/config/routing.yml file, how to fix this?
Edit:
FileLoaderImportCircularReferenceException: Circular reference
detected in "/app/config/routing_dev.yml"
("/app/config/routing_dev.yml" > "/app/config/routing.yml" > "." >
"#GabrielAdminPanelBundle/Controller/" >
"/app/config/routing_dev.yml").
You must also configure service
# src/Gabriel/AdminPanelBundle/Resources/config/services.yml
your_bundle.routing_loader:
class: Gabriel\AdminPanelBundle\Routing\AdvancedLoader
tags:
- { name: routing.loader }
And routing file
# app/config/routing.yml
YourBundle_extra:
resource: .
type: advanced_extra

OneupUploaderBundle: Files are not uploaded and UploadListener not persist to DB, why?

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);
//...
}
}

SonataAdmin - The custom block I'm trying to build is not found

I'm trying to add a custom block to the dashboard of SonataAdminBundle. I followed the instructinos here (How to add custom link or button to SonataAdminBundle Dashboard in Symfony2) and I'm getting the following error :
RuntimeException: The block service `sonata.block.service.processManagement` does not exist
Here's what I did. I have a file named "ProcessManagementBlockService.php" which contains the following:
<?php
namespace IMA\ProcessManagementBundle\Block;
use Symfony\Component\HttpFoundation\Response;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Validator\ErrorElement;
use Sonata\BlockBundle\Model\BlockInterface;
use Sonata\BlockBundle\Block\BlockContextInterface;
use Sonata\BlockBundle\Block\BaseBlockService;
class ProcessManagementBlockService extends BaseBlockService
{
public function getName()
{
return 'My Newsletter';
}
public function getDefaultSettings()
{
return array();
}
public function validateBlock(ErrorElement $errorElement, BlockInterface $block)
{
}
public function buildEditForm(FormMapper $formMapper, BlockInterface $block)
{
}
public function execute(BlockContextInterface $block, Response $response = null)
{
// merge settings
$settings = array_merge($this->getDefaultSettings(), $block->getSettings());
return $this->renderResponse('IMAProcessManagement:Block:blockProcessManagement.html.twig', array(
'block' => $block,
'settings' => $settings
), $response);
}
}
I also created a file (views/Block/blockProcessManagement.html.twig) that contains the template of the block I want to add to SonataAdmin's dashboard :
{% extends 'SonataBlockBundle:Block:block_base.html.twig' %}
{% block block %}
<table class="table table-bordered table-striped sonata-ba-list">
<thead>
<tr>
<th colspan="3">Newsletter - inviare</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="btn-group" align="center">
<a class="btn btn-small" href="#">Servizio Newsletter</a>
</div>
</td>
</tr>
</tbody>
</table>
{% endblock %}
Also, I in the services.yml file of my bundle, I have the following
services:
# ima_process_management.example:
# class: %ima_process_management.example.class%
# arguments: [#service_id, "plain_value", %parameter%]
sonata.block.service.processManagement:
class: IMA\ProcessManagementBundle\Block\ProcessManagementBlockService
arguments: [ "sonata.block.service.processManagement", #templating ]
tags:
- { name: sonata.block }
I know this file is properly loaded because I tried to put the upper lines directly in config.yml and got the same result.
Finally, I added in the main config.yml file of my project
sonata_block:
default_contexts: [cms]
blocks:
# Enable the SonataAdminBundle block
sonata.admin.block.admin_list:
contexts: [admin]
# Your other blocks
sonata.block.service.text:
sonata.block.service.rss:
sonata.admin.block.search_result:
sonata.block.service.processManagement: ~
and
sonata_admin:
templates:
dashboard: SonataAdminBundle:Core:dashboard.html.twig
dashboard:
blocks:
- { position: left, type: sonata.admin.block.admin_list }
- { position: left, type: sonata.block.service.processManagement}
I really don't know why I'm getting the error that the service does not exist...
The problem is how you did the letter casing in the config.yml. Always use lowercase for defining service names if you don't then Symfony converts it to lowercase.
Take a look at the coding standards for Symfony.
Service Naming Conventions:
A service name contains groups, separated by dots
The DI alias of the bundle is the first group (e.g. fos_user)
A service name contains groups, separated by dots
Use lowercase letters for service and parameter names

Categories