How to use Silverstripe 3 beta UploadField - silverstripe

I am trying to use a UploadField on frontend for user to upload their company logo.
There isn't much documentation on UploadField yet. And I have tried it but no luck so far.
Can anyone guide me on how to use it?

This is a little old, but if anyone else stumbles upon this like I did.
UploadField does work frontend. I haven't been able to save into a many_many relationship using the saveInto function. But the biggest thing I missed was the DataObject/Page needs to exist first, as in it needs to be saved before you can attach a related object like an image.
static $has_one = array(
"Photo" => "Image"
);
$fields = new FieldList(
new UploadField( 'Photo', 'Upload' )
);
function saveForm( $data, $form ) {
$object = new DataObject();
// for a new object write before saveinto
$object->write();
$form->saveInto($object);
$object->write();
Director::redirectBack();
}
using ss 3.0.1
Alternatively rather than using the saveinto function you can manually loop over the parameters and attach them on the object yourself for many_many images.

The upload field checks for permissions via the can*() methods in the object.
In order to allow front end editing - you may have to overload File::canEdit (or Image::canEdit) in your custom object to handle this.

Related

Symfony - render twig code in controller

I need to build a customizer for my customers. They will be able to choose between multiple templates for their subdomain.
In order to do that, I took the following path :
Store templates in the DB with twig tags for the user's data
When needing to display a preview of a template, I would get it from the DB
Then I would render it in the controller and send the resulting HTML as a variable to the main template
I'm not succeeding into rendering in the controller. I tried several things, but the closest I got is this :
$loader = new Twig_Loader_Array(array(
'code.html' => $site->getTheme()->getCode(),
));
$twig = new Twig_Environment($loader);
$code = $twig->render('code.html', array( "test" => "CUSTOM DATA" ));
But I miss a use statement :
Attempted to load class "Twig_Loader_Array" from namespace "AppBundle\Controller". Did you forget a "use" statement for another namespace?
I'm not sure if it's the right path though.
So, if it is, please help me find out what use statement to use. More generally, how do you find what use statement should be used ?
If it's not the right strategy according to you, please feel free to explain me how dumb my idea was :)
[EDIT] So thanks to #DarkBee I found this solution that works, but I'm not sure whether I should do this or not :
use Twig\Loader\ArrayLoader;
use Twig\Environment;
...
$loader = new ArrayLoader(array(
'code.html' => $site->getTheme()->getCode(),
));
$twig = new Environment($loader);
$code = $twig->render('code.html', array( "test" => "CUSTOM DATA" ));
So if it's ok, great. If it's wrong (or again, if I'm wrong in the strategy choices), please tell me why and what would be better.

Processing Drupal Node Body

I'm new to Drupal. I looked here and on google for a while before asking, but I'm sure I can't find the answer because I don't know how to ask the question.
Here is what's going on. I'm using a custom module to load certain entities and then output them in a specific format for an application to access. The problem is that the NODE BODY contains special information and media files that should be converted. My goal is to obtain the HTML output that would normally be used on this field.
// Execute an EntityFieldQuery
$result = $query->execute();
if (isset($result['node'])) {
$article_items_nids = array_keys($result['node']);
$article_items = entity_load('node', $news_items_nids);
}
// Loop through each article
foreach ($article_items as $article) {
return $article->body[LANGUAGE_NONE]['0']['value'];
}
All of this works great. The only problem is that I get things like this in the output:
[[{"type":"media","view_mode":"media_original","fid":"283","attributes":{"alt":"","class":"media-image","data-thmr":"thmr_32","height":"400","width":"580"}}]]
or
*protoss_icon*
My goal is to find a way that these items are converted just like they are when these articles are viewed normally.
I've tried doing things such as:
render(field_view_field('node', $article, 'body'));
or
render($article->body[LANGUAGE_NONE]['0']['value']);
without success. Thanks for any help, I'm learning so I don't have a complete grasp of the process drupal uses to build output.
You can try something like this (this works only with nodes not with other custom entity types):
$node = node_load($nid);
$field = field_get_items('node', $node, 'your_field_name');
$output = field_view_value('node', $node, 'your_field_name', $field[$delta]);
the field_view_value returns a renderable array for a single field value. (from drupal api documentation)

Silverstripe Gridfield Relation

I am attempting to update the secure files silverstripe module to SS3.
In it, the author uses the following ComplexTableField:
class SecureFileTokenPermissionDecorator extends DataExtension {
static $has_many = array(
'AccessTokens' => 'SecureFileAccessToken'
);
....
$tokenList = new ComplexTableField(
$this->owner,
'ContainedFileTokens',
'SecureFileAccessToken',
null,
null,
"File.ParentID = '{$this->owner->ID}'",
$sourceSort = null,
"JOIN File ON FileID = File.ID"
));
$tokenList->setParentIdName('FolderID');
$tokenList->setRelationAutoSetting(false);
....
}
I was wondering how I would go about representing the same data/relation with gridfField.
Thanks!
Looking at the secure files module source code, I would suggest the following setup:
$tokenList = $gridField = new GridField(
'AccessTokens',
'Tokens',
$this->owner->AccessTokens(),
GridFieldConfig_RelationEditor::create()
);
This works directly on the relation getter, which is a lazy loaded list (not queried until necessary), and automatically paginated. I'm not quite sure how the setParentIdName("FolderID") fits in here, probably unnecessary. Caution: Haven't tried this on the actual codebase.
If you need some help understanding the API on a higher level, have a look in the GridField docs and the "datamodel" topic.
Thanks for helping to make modules ready for SS3! :)

How to create a unique form using multiple entities fields in symfony2

I want to create a form using some fields from multiple entities. I have all the distinct entites needed already created and i am not using form classes. I need to know how to do to render a form and handle its data so i can save them to the correct tables in my database.
Here is a part of my controller in charge of doing that
public function createPublicSpaceAction() {
//My entities
$Room = new Room();
$GuestList = new GuestList();
$Guest = new Guest();
//I need to know what to do from here
return $this -> render('AcmeUserBundle:Default:Forms/createPublicSpace.html.twig', array());
}
I kept trying to find a solution and i came up with the idea that one form needs one entity. So maybe the solution would be to merge those entities in one so i can build the form easily. I would then have to persist data to corresponding tables. But i can't think of how to merge entities.
I figured out a temporary solution. For those who want to know, I manually created an entity that looks like a merge of all the entity I need. This new entity has no link with Doctrine therefore it cannot create a table. Its goal is simply to allow me to build up a form and be able to manipulate data through that form. I then assign all data submitted to corresponding entities fields and persist them to the database.
Once again i know this is not the best solution. But for some reasons I won't tell, it is for me at this moment. I hope this can help some that are in the same situation than me and do not hesitate to post links that could help or better ways to do that.
It is highly recommended to use form classes http://symfony.com/doc/current/book/forms.html#creating-form-classes
They are designed to save time and make a lot of things just easier.
However to answer your question consider the following. Your action needs to handel a post request. So catch the request object with the post data:
use Symfony\Component\HttpFoundation\Request;
public function createPublicSpaceAction(Request $request)
Then get a form builder intance and create the form:
$builder = $this->createFormBuilder();
$builder->add('floor', 'text', array(
'label' => 'Room floor',
'data' => $room->getFloor()
));
add as much form fields as you need. There are several built-in field types: http://symfony.com/doc/current/book/forms.html#built-in-field-types
Create the form:
$form = $builder->getForm();
Pass the form to your template:
return $this -> render('AcmeUserBundle:Default:Forms/
createPublicSpace.html.twig', array(
'roomForm' = $form
));
To get posted data within your action:
if ('POST' == $request->getMethod()) {
$data = $request->request->get("form");
}
And in your template you can render the form by yourself or let twig do the job:
{{ form_widget(form.floor)}}
So this are the most importend things to mention. However you should go through http://symfony.com/doc/current/book/forms.html They actually tell you everything I wrote down.
Good luck ;)

Adding avatar to $user in Drupal 7

I've created a simple module for displaying a flash game in a custom block by overwriting game_block_view() and game_block_info() in the sites/default/modules/game.module and it works ok.
I need however to pass user avatar and also gender and city (I've added the 2 mandatory fields to the registration form) through the FlashVars-parameter to the flash game in my block.
So I'm trying to overload the hook_user_load, because I suppose that this is the method where you add properties to the $user object after it has been initiated from the database (this probably happens when the user logins or alters his/her profile data?):
function game_user_load($users) {
global $user;
$uid = $user->uid;
$result = db_query('select filename from {file_managed} where uid=:uid', array(':uid' => array($uid)));
$avatar = $result->fetchField();
$users[$uid]->avatar = $avatar;
drupal_set_message("<pre>$uid: $avatar</pre>\n");
print_r($users);
}
Unfortunately I see no output produced by the last 2 lines above in the web page
What am I doing wrong?
Thank you!
Alex
The global user object does not go through hook_user_load(), see http://api.drupal.org/api/drupal/includes--session.inc/function/_drupal_session_read/7. Don't ask me why, that's just the way it is :)
When using user_load(), any added fields will automatically be loaded, you don't need custom code for that. You just need to know how to access them, which is a bit complicated.
Something like this should work:
global $user;
// $account is now a fully loaded user object.
$account = user_load($user->uid);
// Your field name is probably 'field_avatar'.
if ($avatar = field_get_items('user', $account, 'field_avatar')) {
dpm($avatar); // only works with devel.module, strongly suggested!
}

Resources