How to save all but one field in Doctrine + ZF2? - doctrine-orm

I have a User entity and in the edit Action I present a form to edit the user. I would like to have a password field available. If the password is blank, then I would like to update all field except the password, and if something is entered then all fields would be updated.
Here is my controller action.
public function editUserAction() {
$id = (int) $this->params()->fromRoute('id', 0);
if (!id) return $this->redirect()->toRoute('index', array('action' => 'users));
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$form = new UserForm($objectManager);
$user = $objectManager->find('Application\Entity\User', $id);
$form->bind($user);
if ($this->request->isPost()) {
$form->setData($this->request->getPost());
if ($form->isValid()) {
$data = $this->request->getPost();
if ($data->user['password'] == '') {
// how to save all but one field
}
else {
$objectManager->persist($user);
$objectManager->flush();
}
}
}
}

use the remove method:
vendor/zendframework/zendframework/library/Zend/Form/Fieldset.php
remove Remove a named element or fieldset
Parameters:
 
string
$elementOrFieldset
PHPDoc not found
Returns:
 
Type:
FieldsetInterface
if ($data->user['password'] == '')
{
$form->remove('password');
$objectManager->persist($user);
$objectManager->flush();
}

Related

Setting id in ember data with createRecord

If I try to create a record with something like
var myObject = App.ModelName.createRecord( data );
myObject.get("transaction").commit();
the id of myObject is never set.
This says that id generation should be handled by EmberData (first response). So what should be happening? Where is the new id determined. Shouldn't there be a callback to the API to get valid id?
ID is the primary key for your record which is created by your database, not by Ember. This is JSON structure submit to REST post, notice no ID.
{"post":{"title":"c","author":"c","body":"c"}}
At your REST Post function you must get the last insert ID and return it back with the rest of the model data to Ember using this following JSON structure. Notice the ID, that is the last insert ID. You must get that last insert ID manually using your DB api.
{"post":{"id":"20","title":"c","author":"c","body":"c"}}
This is my sample code for my REST post. I coded this using PHP REST Slim framework:
$app->post('/posts', 'addPost'); //insert new post
function addPost() {
$request = \Slim\Slim::getInstance()->request();
$data = json_decode($request->getBody());
//logging json data received from Ember!
$file = 'json1.txt';
file_put_contents($file, json_encode($data));
//exit;
foreach($data as $key => $value) {
$postData = $value;
}
$post = new Post();
foreach($postData as $key => $value) {
if ($key == "title")
$post->title = $value;
if ($key == "author")
$post->author = $value;
if ($key == "body")
$post->body = $value;
}
//logging
$file = 'json2.txt';
file_put_contents($file, json_encode($post));
$sql = "INSERT INTO posts (title, author, body) VALUES (:title, :author, :body)";
try
{
$db = getConnection();
$stmt = $db->prepare($sql);
$stmt->bindParam("title", $post->title);
$stmt->bindParam("author", $post->author);
$stmt->bindParam("body", $post->body);
$stmt->execute();
$insertID = $db->lastInsertId(); //get the last insert ID
$post->id = $insertID;
//prepare the Ember Json structure
$emberJson = array("post" => $post);
//logging
$file = 'json3.txt';
file_put_contents($file, json_encode($emberJson));
//return the new model back to Ember for model update
echo json_encode($emberJson);
}
catch(PDOException $e)
{
//$errorMessage = $e->getMessage();
//$data = Array(
// "insertStatus" => "failed",
// "errorMessage" => $errorMessage
//);
}
}
With some REST adapters, such as Firebase, you can define the id as a variable of the record you are going to create.
App.User = DS.Model.extend({
firstName: DS.attr('string')
});
var sampleUser = model.store.createRecord('user', {
id: '4231341234891234',
firstName: 'andreas'
});
sampleUser.save();
JSON in the database (Firebase)
"users": {
"4231341234891234": {
"firstName": "andreas"
}
}

Is it possible to set the current user name to a field of an item in sitecore cms?

For example, my username in the sitecore admin is "Borj", whenever I create an article I want "Borj" to be automatically fill the author field of any article I would create.
Yes, this is possible, but will require some customization.
By default you only have the following tokens:
$name: Is replaced with the name of the created item
$parentname: Is replaced with the name of the parent to the created item
$date: Is replaced with the current date
$time: Is replaced with the current time
$now: Is replaced with current date and time
$id: Is replaced with the id of the created item
$parentid: Is replaced with the id of the parent to the created item.
This post by John West shows you exactly how to fill a field with the name of the user that's creating the item.
This is the code he uses:
public class MasterVariablesReplacer : SC.Data.MasterVariablesReplacer
{
public override string Replace(string text, SC.Data.Items.Item targetItem)
{
SC.Diagnostics.Assert.ArgumentNotNull(text, "text");
SC.Diagnostics.Assert.ArgumentNotNull(targetItem, "targetItem");
string result = this.ReplaceValues(
text,
() => targetItem.Name,
() => targetItem.ID.ToString(),
() => SC.Data.Items.ItemUtil.GetParentName(targetItem),
() => targetItem.ParentID.ToString());
return result;
}
private string ReplaceValues(
string text,
Func<string> defaultName,
Func<string> defaultId,
Func<string> defaultParentName,
Func<string> defaultParentId)
{
if ((text.Length != 0) && (text.IndexOf('$') >= 0))
{
SC.Text.ReplacerContext context = this.GetContext();
if (context != null)
{
foreach (KeyValuePair<string, string> pair in context.Values)
{
text = text.Replace(pair.Key, pair.Value);
}
}
text = this.ReplaceWithDefault(text, "$name", defaultName, context);
text = this.ReplaceWithDefault(text, "$id", defaultId, context);
text = this.ReplaceWithDefault(text, "$parentid", defaultParentId, context);
text = this.ReplaceWithDefault(text, "$parentname", defaultParentName, context);
text = this.ReplaceWithDefault(text, "$date", () => SC.DateUtil.IsoNowDate, context);
text = this.ReplaceWithDefault(text, "$time", () => SC.DateUtil.IsoNowTime, context);
text = this.ReplaceWithDefault(text, "$now", () => SC.DateUtil.IsoNow, context);
text = this.ReplaceWithDefault(text, "$user", () => SC.Context.User.LocalName, context);
}
return text;
}
private string ReplaceWithDefault(
string text,
string variable,
Func<string> defaultValue,
SC.Text.ReplacerContext context)
{
if ((context != null) && context.Values.ContainsKey(variable))
{
return text;
}
if (text.IndexOf(variable, StringComparison.InvariantCulture) < 0)
{
return text;
}
return text.Replace(variable, defaultValue());
}
}
If you then change the setting MasterVariablesReplacer to your own assembly and class, it'll also pick up on $user
In this post Alistair Deneys shows a different way of doing it as well.
[edit]
Please do note that the (untested) code provided above will not work with branches - just with the 'usual' way of creating items.
Sitecore already stores the user who created an item in the __created field if you just want to display the user name on the front end web site you could just use that field and strip off the domain i.e. sitecore\

How to flush zend_form to multiple entities

I'm struggling with flushing my zend_form to 2 entities. In total I've 3 entities. User, Address and Country. Country is not interesting because it has standard values where only the ID come into Address. My add-action works good (only when I keep my address/country empty, it puts a new record in the database so I've to fix this). But my edit only flushes my latest bind. My edit-action:
/**
* Edit action for single user
*
* #return route zfcadmin/user/add
* #return route zfcadmin/user
* #return array(id, form, flashMessages)
*/
public function editAction()
{
$id = (int)$this->getEvent()->getRouteMatch()->getParam('id');
if (!$id) {
return $this->redirect()->toRoute('zfcadmin/user/', array('action' => 'add'));
}
//Get user with the id (given in URL), and pick his address(es)
$user = $this->getEntityManager()->find('User\Entity\User', $id);
$addresses = $user->addresses;
$form = new UserForm();
//Set country values out of the entity
$form = $this->fillCountrySelectbox($form);
$form->bind($user);
//Get addresses from the user, and bind it to the $form
foreach($addresses as $address) {
//If user has address, bind the addresses
if(isset($address)) {
$form->bind($address);
}
}
$form->get('save_goback')->setAttribute('value', 'Save');
$form->get('save')->setAttribute('value', 'Save & Stay');
$request = $this->getRequest();
if ($request->isPost()) {
//Set the inputfilter on the input values
$inputFilter = new InputFilter();
//Set filters from different entities
$inputFilter = $user->setFilters($inputFilter);
$inputFilter = $address->setFilters($inputFilter);
//Set the inputFilter on the form
$form->setInputFilter($inputFilter);
$form->setData($request->getPost());
if ($form->isValid()) {
$form->bindValues();
//set complete country object in address entity.
$country = $this->getEntityManager()->find('User\Entity\Country', $form->get('country')->getValue());
$address->__set('country', $country);
//Set country Null when no country was selected, otherwise it conflict with country entity (because no '' is set)
if($address->country == '') {
$address->country = NULL;
}
//Set modifier (current user)
$address->__set('last_modifier_id', $this->zfcUserAuthentication()->getIdentity()->getId());
$this->flashMessenger()->addMessage('User saved');
$this->getEntityManager()->flush();
if ($this->getRequest()->getPost('save_goback')) {
return $this->redirect()->toRoute('zfcadmin/user');
}
}
}
return array(
'id' => $id,
'form' => $form,
'flashMessages' => $this->flashMessenger()->getMessages()
);
}
When I not bind the address, it will flush to the user-entity, and when I bind the address, it flushes to address only, so my edits on the user won't work. How can I edit my form, with saving the user AND address?

Symfony2 authenticating users through a webservice

I'm currently dealing with Symfony2's Security component.
I try to authenticate users against a webservice. To authenticate a user, I have to provide to the webservice a username and a password.
I know that I've got to create a class that implements UserProvider. But the loadUserByUsername function doesn't fit my webservice needs : in order to authenticate a user, it ask for both username and password whereas the UserProvider's function only requires username.
Here is a similar question to the problem I face : Symfony2 authentication without UserProvider
I've been struggling on this problem for a couple of days...
I fixed this problem in that way:
services.yml:
services:
user_provider:
class: "%my_class%"
arguments: ["#service_container"]
WebServiceUserProvider.php
/**
* #param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->apiClient = $container->get('api_client');
$this->request = $container->get('request');
}
and use $password = $this->request->get('password'); in your loadUserByUsername method
One way of accomplishing this would be to load the user by the username and then validate the password. If the a user exists for the given username and the password entered matches with the password of that user, then authenticate the user.
Example:
public function userLogin($username, $password)
{
$em = $this->getEntityManager();
$query = $em->createQuery('SELECT u FROM VenomCoreBundle:User u WHERE u.username = :username OR u.email = :username AND u.isDeleted <> 1 ')
->setParameter('username', $username);
try {
$entity = $query->getSingleResult();
if (count($entity) > 0) {
$encoder = new MessageDigestPasswordEncoder('sha512', true, 10);
$passwordEnc = $encoder->encodePassword($password, $entity->getSalt());
$userPassword = $entity->getPassword();
if ($passwordEnc == $userPassword) {
$tokenValue = $entity->getUserToken();
$profile = $entity->getUserProfile();
if(!$profile) {
return false;
}
$userName = $profile->getFullName();
$response = array(
'token' => $tokenValue,
'username' => $userName
);
} else {
return false;
}
}
} catch (\Doctrine\Orm\NoResultException $e) {
return false;
}
return $response;
}

How can I add a related entity to a user object at the point of creation in FOSUserBundle?

In Symfony2 RC3, I am trying to create a related entity on a User object (FOSUserBundle) at the point of user creation so that I can display the appropriate fields on an edit profile form. I am doing the following in the RegistrationFormHandler.
class RegistrationFormHandler
{
protected $request;
protected $userManager;
protected $form;
public function __construct(Form $form, Request $request, UserManagerInterface $userManager)
{
$this->form = $form;
$this->request = $request;
$this->userManager = $userManager;
}
public function process($confirmation = null)
{
$user = $this->userManager->createUser();
$this->form->setData($user);
if ('POST' == $this->request->getMethod()) {
$this->form->bindRequest($this->request);
if ($this->form->isValid()) {
if (true === $confirmation) {
$user->setEnabled(false);
} else if (false === $confirmation) {
$user->setConfirmationToken(null);
$user->setEnabled(true);
}
$prog = new \MyBundle\CoreBundle\Entity\Programme();
$prog->setStartDate(date_create());
$prog->setEndDate(date_create());
$prog->setWeeklyTarget(4);
$prog->setGoal('');
$user->addProgrammes($prog);
$this->userManager->updateUser($user);
return true;
}
}
return false;
}
}
The programme record does get created in the database but with a null user_id so it seems the association isn't working correctly. Anyone know what might be causing this?
The solution was to do $programmes->setUser($this); in the addProgrammes method of my User entity