Symfony 3, is it possible to use a variable in a path? - symfony

I am working on a project, and I would like to be able to use variables in paths directly. This may seem strange, but imagine I have
mysite.org/admin
I take precautions to stop people accessing admin, ofcourse. But for peace of mind, and the clients peace of mind, it would be nice to allow the client to choose this path, and even change it every so often.
Yes I could just change the path manually, and it would take 2 seconds, but it would just be nice if this was a possibility at all.
I'm using annotation for my routing, but I am interested in any answers if not just for curiosities sake.
Is it possible to store this in config.yml, and then use this in your path? I have been searching but not found anything on the subject.

You could do something like this:
/**
* #Route("/admin/{admin_path}")
*/
public function adminAction(Request $request, $admin_path)
{
//code to verify if admin_path is currently the good one using database or another way
if (false === is_admin_path_the_right_one($admin_path)) {
$this->redirectToRoute('index');
}
//show admin
}
I prefixed with /admin because otherwise every other route would match this action. But you could use something else like /a/

Related

Symfony2 best way of removing business logic from controller and correct usage of model

I'm in searching of the best way of removing business logic from controller and correct usage of model(and maybe services).
Some details below.
Actually, my project is more complicated, but as example I will use Simple Blog application.
I have created my application (Simple Blog) in next steps:
created bundle
generated entities(Topic, Post, Comment)
generated controller for each entity, using doctrine:generate:crud
installed FOSUserBundle and generated User entity
So, I have all needed methods and forms in my controllers. But now I have some troubles:
Admin need to be able see all topics and posts, when simple User can only see
topic and posts where he is owner.
Currently there are indexAction, that return findAll common for any user. As solution, I can check in action, if ROLE_USER or ADMIN and return find result for each condition. But this variant keep some logic at action.
I also can generate action for each role, but what happened if roles amount will increase?
What is the best way to solve this problem with result for each role?
I need to edit some parameters before saving.
For example, I have some scheduler, where I create date in some steps, using features of DateTime.
Before saving I need to do some calculations with date.
I can do it in controller using service or simple $request->params edit.
What is the best way to edit some $request parameters before saving?
My questions I have marked with bold.
Thanks a lot for any help!
What I would do is to create a query which fetches the topics. Afterwards I would have a method argument which specifies if the query should select only the topics for a certain user or all topics. Something like this should do the work in your TopicRepository:
public function findTopics($userId = false)
{
$query = $this->createQueryBuilder('topic');
if($userId) {
$query->join('topic.user', 'user')
->where('user.id = :user_id')
->setParameter(':user_id', $userId)
;
}
return $query->getQuery()->getResult();
}
So, whenever you need to get the topics only by a user, you would pass a $userId to the method and it would return the results only for that user. In your controller you'd have something similar to this code (Symfony 2.6+):
$authorizationChecker = $this->get('security.authorization_checker');
if($authorizationChecker->isGranted('ROLE_ADMIN')){
$results = $this->get('doctrine.orm.entity_manager')->getRepository('TopicRepository')->findTopics();
} else {
$results = $this->get('doctrine.orm.entity_manager')->getRepository('TopicRepository')->findTopics($this->getUser()->getId());
}
You can try using Doctrine Events and create a PreUpdate depending on your case. See the documentation for more information. If you have a TopicFormType, you could also try the form events.
You are not supposed to "edit" a $request, which is why you can't directly do that. You can, however, retrieve a value, save it as a $variable and then do whatever you want with it. You can always create a new Request if you really need it. Could you be more specific what you want to do here and why is this necessary?

Doctrine2 , generate on a fly the value of a Entity's attribute that depends on symfony2 container

I have an API, with an API call GET /users which returns me a list of users that all have a avatar_url field
in database this field is just the image name, and in the controller i'm then putting the base URL of my static domain serving images. So that it's only one URL to change in my conf , so the code works in staging/production etc.
but things start to get tricky with GET /comments etc. that all have sub-resource users that needs to have the url, so it means that currently every single point using users needs to have this logic, which is not very DRY
I would like to have something like that
// in my entity
use JMS\Serializer\Annotation as Serializer;
/**
* #Serializer\VirtualProperty
* #Serializer\SerializedName("url")
*/
public function getUrl()
{
return $this->container->getParameter('IMG_URL').$this->imgName;
}
so that regardless on how deeply nested my entity is, I will be able to seralize it with the property.
It seems to me it is possible to achieve something like as there's a bundle
https://github.com/KnpLabs/DoctrineBehaviors
which seems to achieve something similar
Check this out. http://jmsyst.com/libs/serializer/master/handlers
From what I understand you could create your own handler for the url serializer. By having the handler as a service written by you, then you can inject anything you want in it.
More info can be found at Creating a JMS Serializer handler in symfony2

Custom Assetic Filter Development - Constantly Cached?

I'm having an issue with my development of a custom assetic filter. I loosely followed the steps in the blog article found here and got things working for the most part. The thing that's causing me hang up is the fact that if I make a change to the filterLoad or filterDump methods it usually shows up the first time but additional changes won't. It seems like things are getting cached but not in the usual Symfony2 cache directory. This is pretty vague so far so let me know if there's any additional information I can provide.
Example of change:
public function filterLoad(AssetInterface $asset)
{
$asset->setContent('this');
}
public function filterDump(AssetInterface $asset)
{
$asset->setContent('that');
}

Access Session from EntityRepository

I'm using Symfony2 with Doctrine2. I want to achieve the following:
$place = $this->getDoctrine()->getRepository('TETestBundle:Place')->find($id);
And on that place will be the info of the place (common data + texts) on the user language (in session). As I am going to do that hundreds of times, I want to pass it behind the scenes, not as a second parameter. So an English user will view the place info in English and a Spanish user in Spanish.
One possibility is to access the locale of the app from an EntityRepository. I know it's done with services and DI but I can't figure it out!
// PlaceRepository
class PlaceRepository extends EntityRepository
{
public function find($id)
{
// get locale somehow
$locale = $this->get('session')->getLocale();
// do a query with the locale in session
return $this->_em->createQuery(...);
}
}
How would you do it? Could you explain with a bit of detail the steps and new classes I have to create & extend? I plan on releasing this Translation Bundle once it's ready :)
Thanks!
I don't believe that Doctrine is a good approach for accessing session data. There's just too much overhead in the ORM to just pull session data.
Check out the Symfony 2 Cookbook for configuration of PDO-backed sessions.
Rather than setting up a service, I'd consider an approach that used a Doctrine event listener. Just before each lookup, the listener would pick out the correct locale from somewhere (session, config, or any other place you like in the future), inject it into the query, and like magic, your model doesn't have to know those details. Keeps your model's scope clean.
You don't want your model or Repository crossing over into the sessions directly. What if you decide in the future that you want a command-line tool with that Repository? With all that session cruft in there, you'll have a mess.
Doctrine event listeners are magically delicious. They take some experimentation, but they wind up being a very configurable, out-of-the-way solution to this kind of query manipulation.
UPDATE: It looks like what you'd benefit from most is the Doctrine Translatable Extension. It has done all the work for you in terms of registering listeners, providing hooks for how to pass in the appropriate locale (from wherever you're keeping it), and so on. I've used the Gedmo extensions myself (though not this particular one), and have found them all to be of high quality.

Drupal node creation - back to origin after creation

I have organic groups setup and within those group users are allowed to post certain content.
What I woulkd like to do is, when you create a node inside an organic group, it automatically defaults back to frontpage of the group, or the same page that I used to create the node.
At present it defaults to the node view page.I assume there must be a way to add some kind of code so that after the node creation it defauls back to its origin. I.E. the page from where the node was created from.
thanks :)
UPDATE: Got the below, but not entirly sure how to ensure that it redirects back to the GROUP node, from where it was created,
<?php
/**
* Grabs current node ID
*/
$node_nid = nid;
/**
* Implements hook_form_alter().
*/
function mod_form_alter(&$form, $form_state) {
$form['buttons']['submit']['#submit'][] = 'mod_form_finish_redirect';
unset($form['buttons']['preview']);
}
/**
* Custom submit handler. Overwrites the form redirection variable.
*/
function mod_form_finish_redirect($form, &$form_state) {
$form_state['redirect'] = '/content/<?php print $node_nid; ?>';
}
?>
I would recommend the rules module. Rules is a great module that allows you to do many kinds of workflow and it is perfect for this. You can write a rule that triggers when a specified node type is created (and include any other conditions you require as well). After the node is created you can specify a redirect action rule to the home page. This can all be done without any code.
Rules (as 'We Love Drupal' says) is a possibility, but also quite a big module for such a small change in behavior. Another option is to write a custom module implementing hook_form_alter setting the #redirect value of the form.
Keep in mind that of seeing the node you have just created is important feedback for a user. When you perform an action, you want confirmation that you have achieved your task. While it's technically possible to do what you ask, it may be bad for usability.
I had the same requirment. Rules worked for me.

Resources