symfony - adding a user to a group (sfGuardUserGroup) in a form - symfony1

I'm trying to save some users in a custom admin form and I'd like to set them in a particular group, in the sfGuardUserGroup.
So If the user I've just created has an id of 25, then I'd expect an entry in the sfGuardUserGroup table with a user_id of 25 and a group_id of 8 (8 is my group id I want o add these users to.)
Could I do this in the form class, or in the processForm action?
I'm using doctrine and SF1.4
Thanks

This should do what you need:
<?php
class AdminUserForm extends sfGuardUserForm
{
public function configure()
{
//customise form...
}
public function save($con = null)
{
//Do the main save to get an ID
$user = parent::save($con);
//Add the user to the relevant group, for permissions and authentication
if (!$user->hasGroup('admin'))
{
$user->addGroupByName('admin');
$user->save();
}
return $user;
}
}

If you require this behaviour for all sfGuardUser's created you should put this logic in the model for sfGuardUser class. [example below]
// sfGuardUser class
public function save(Doctrine_Connection $conn = null) {
if (!$this->hasGroup('group_name'))
$this->addGroupByName('group_name', $conn);
parent::save($conn);
}
If you require this functionality only on this specific form, you should put the logic within the form. Adding logic to the processForm action would be incorrect as you would be placing business logic within the controller.

Related

MVC4 - ActionLink to either Create() or, if already existing, Edit(Id)

I would like an action link that says "set user default". There's a possibility the database does not already have the UserDetails stored for the user who clicks the link. If this is the case, I would like to direct the user to the Create view when they can save a new object.
If the UserDetails already exists for the user, I would like to direct the user to their Edit(id) page and load their existing UserDetails from the database.
Basically I need an ActionLink that points to a different view based on some information.
What is the preferred/standard way in MVC to accomplish this?
Existing Record
#Html.ActionLink("set user default", "Edit", "User")
Non-Existing Record
#Html.ActionLink("set user default", "Create", "User")
This was an attempt I made however it didn't work since EditOrCreate needs to be a view - ideally this scenario would not require the creation of another view.
public ActionResult EditOrCreate()
{
User user = Get(User.Identity.Name);
if (user != null)
Edit(user);
else
Create();
}
You can achieve that by having action link to SetUserDefault action method such as
#Html.ActionLink("set user default", "SetUserDefault", "User")
Inside the action method detect the user type and then redirect the user to the right action
public ActionResult SetUserDefault()
{
User currentUser = Get(User.Identity.Name);
if (currentUser != null)
return RedirectToAction("Edit", new { id = currentUser.Id });
else
return RedirectToAction("Create");
}

How use URL ZF2 in my Entity Class

I must insert a link in an email that send to my user. So I have an Entity class that send this mail. But I don't know how i can create this link with "url" method of the view/controller system of ZF2.
My class is:
class UserEntity
{
public function sendMail($user)
{
$link = $unknow->url("route",array("param" => "param")); //how can create this ?
$text = "click here $link";
$this->sendMail($to,$text);
}
}
Can you help me? Thanks
In terms of design, it would be considered bad practice to have your domain model responsible for the creation of the URL (or anything else that that does not describe the entity in its simplest terms).
I would create a UserService that would encapsulate the a SendMail function where a UserEntity could be passed as an argument and it's email property used to send the email.
class UserService {
protected $mailService;
public function __construct(MailService $mailService) {
$this->mailService = $mailService;
}
public function sendUserEmail(UserEntity $user, $message) {
$this->mailService->send($user->getEmail(), $message);
}
}
The mail service could be another service encapsulating the Zend\Mail\Transport instances.
Your controller would use the UserService to send the mail to the correct user.
The $message which needs to include a URL that is generated using the Zend\Mvc\Controller\Plugin\Url controller plugin
class UserController extends AbstractActionController {
protected $userService;
public function __construct(UserService $userService) {
$this->userService = $userService;
}
public function sendEmailAction() {
// load $user from route params or form post data
$user = $this->userService->findUserByTheirId($this->params('id'));
// Generate the url
$url = $this->url()->fromRoute('user/foo', array('bar' => 'param1'));
$message = sprintf('This is the email text link!', $url);
$this->userService->sendUserEmail($user, $message);
}
}
These are contrived examples but my point is that you should only store information in your entity allowing you to "do stuff" with it, not within it.

Symfony 1.4 : Hide a widget and its validator, based on a cookie?

On my website, I use a ReCaptcha widget in the form used to add comments. Once the form has been correctly sent, I write a cookie to the user's computer.
I would like to remove the ReCaptcha widget when the user has that cookie, so that returning visitors don't have to type a captcha. Can I do that in forms/commentForm.class.php, or do I need to create a new form ?
Save your flag in session:
<?php
...
if ($form->isValid()) {
...
// comment added
$this->getUser()->setAttribute('is_bot', false);
...
}
In another action:
<?php
$this->form = new CommentForm();
if ($this->getUser()->getAttribute('is_bot', true)) {
$this->form->setWidget(); // set captcha widget
$this->form->setValdiator(); // set captcha valdiator
}
Hope this helps.
It is often handy to pass a User instance as an option when creating a form in action:
public function executeNew(sfWebRequest $request)
{
$this->form = new ModelForm(null, array('user'=>$this->getUser));
}
Now you can configure you form based on user session attributes:
class ModelForm extends BaseModelForm
{
public function configure()
{
if ($this->getOption('user')->getAttribute('is_bot', false)
{
//set your widgets and validators
}
}
}

allow users to change their own password, email and Profile

I'm creating my own blog engine to learn Symfony, and I have a question :
I can add and edit users thanks to the sfGuardUser module, but how can I allow users to edit only their reccord ?
Users should have access to a page allowing them to edit their email, name, password, and Profile.
Any ideas ?
In the action where the profile is updated you retrieve the users object via the getId() method and apply the changes on the returning object.
$user = sfGuardUserPeer::retrieveByPK(
$this->getUser()->getGuardUser()->getId()
);
I found the following code, will try it tonight.
class sfGuardUserActions extends autoSfGuardUserActions {
public function executeEdit(sfWebRequest $request) {
$this->checkPerm($request);
parent::executeEdit($request);
}
public function checkPerm(sfWebRequest $request) {
$id = $request->getParameter('id');
$user = sfContext::getInstance()->getUser();
$user_id = $user->getGuardUser()->getId();
if ($id != $user_id && !($user->hasCredential('admin'))) {
$this->redirect('sfGuardAuth/secure');
}
} }
from http://oldforum.symfony-project.org/index.php/m/96776/

Taking advantage of Doctrine relations in frontend applications in Symfony

Let's consider the following simple schema (in Doctrine, but Propel users are welcome too):
User:
columns:
name: string
Article:
columns:
user_id: integer
content: string
relations:
User:
local: user_id
foreign: id
Now, if you create a route for Article model and generate a module via doctrine:generate-module-for-route frontend #article_route you get a CRUD application that manages all the articles. But in frontend you would normally want to manage objects related to signed-in User, so you have to manually get the id of the User, pass id to the model and write a bunch of methods that would retrieve objects related to this User, for example:
public function executeIndex(sfWebRequest $request)
{
$this->articles = Doctrine::getTable('Articles')
->getUserArticles(this->getUser());
}
public function executeShow(sfWebRequest $request)
{
$this->article = $this->getRoute()->getObject();
if (!$this->article->belongsToUser($this->getUser()))
{
$this->redirect404();
}
}
and model:
class ArticleTable extends Doctrine_Table
{
public function getUserArticles(sfUser $user)
{
$q = $this->createQuery('a')
->where('a.user_id = ?', $user->getId());
return $q->execute();
}
}
class Article extends BaseArticle
{
public function belongsToUser(sfUser $user)
{
return $this->getUserId() == $user->getId();
}
}
This is trivial stuff and yet you have to manually write this code for each new relation. Am I missing some kind of way to take advantage of Doctrine relations? Anyways, how would you do it? Thank you.
I believe you should be able to do this with a custom routing class. I have never done this, but there is a tutorial in the More with Symfony book: Advanced Routing. My guess is that it should look something like this:
class objectWithUserRoute extends sfDoctrineRoute
{
public function matchesUrl($url, $context = array())
{
if (false === $parameters = parent::matchesUrl($url, $context))
{
return false;
}
$parameters['user_id'] = sfContext::getInstance()->getUser()->getId();
return array_merge(array('user_id' => sfContext::getInstance()->getUser()->getId()), $parameters);
}
protected function getRealVariables()
{
return array_merge(array('user_id'), parent::getRealVariables());
}
protected function doConvertObjectToArray($object)
{
$parameters = parent::doConvertObjectToArray($object);
unset($parameters['user_id']);
return $parameters;
}
}
You would then need to set the routing class in routing.yml to use objectWithUserRoute. I haven't tested this, but I think it is the best way to go about solving the problem.

Resources