Output to template, which variable to use? - silverstripe

I have a template which needs to display users that have been assigned to that page via GridField.
When a user is assigned to the page their ID is stored, I am then retrieving that info like so
class Shows_Controller extends Page_Controller {
# Get key people from ShowsContact class / input via ShowsContact GridField
public function getKeyPeople(){
if($this->ShowsContacts()->exists()){
$result = array();
foreach($this->ShowsContacts()->column('MemberID') as $teamMemberID){
array_push($result, Member::get()->byID($teamMemberID)->Nickname);
}
var_dump($result); # Using var_dump here to see if I get what I need...
}
}
}
I have tried using SilverStripes ArrayList but couldn't get that to work either - here's the same thing but using ArrayList...
$result = new ArrayList();
foreach($this->ShowsContacts()->column('MemberID') as $teamMemberID){
$result->add(Member::get()->byID($teamMemberID)->Nickname);
}
var_dump($result);
The output of this is what I'm expecting but I don't understand how to loop through the results and what variable I need to use so that the loop displays the results within my template..?
The result from the var_dump is this, I need to get those names out to the relevant part of the webpage
array(3) {
[0]=>
string(6) "vlad-s"
[1]=>
string(10) "lawrence-r"
[2]=>
string(8) "darren-g"
}
I've also made attempts at using <% with %> but that didn't work either
Edit
Just to mention, I'm only trying to obtain the usernames at the moment but will need to get multiple things from the ID such as Firstname, Surname, ImageURL

Wow finally got it working how I needed it to!
What I was missing was using ArrayData() when trying to add to the ArrayList()
Here's the working code
class Shows_Controller extends Page_Controller {
# Get key people from ShowsContact class // input via ShowsContact GridField
public function getKeyPeople(){
if($this->ShowsContacts()->exists()){
$result = new ArrayList();
foreach($this->ShowsContacts()->column('MemberID') as $teamMemberID){
$result->add(new ArrayData(array(
'Nickname' =>Member::get()->byID($teamMemberID)->Nickname
)
));
}
return $result;
}
}
}
And now in my template I can use
<% loop KeyPeople %>
$Nickname
<% end_loop %>
To get the data out where I need it!

Related

Array as parameter in Doctrine SQLFilter

I'm trying to create Doctrine SQLFilter. I need to filter for "deleted" field. But i want to make filter works with both (true and false) values too.
Something like this:
<?php
namespace Rem\CostsBundle\Doctrine;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\Filter\SQLFilter;
class ItemDeletedFilter extends SQLFilter
{
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
if ($targetEntity->getReflectionClass()->name != 'Rem\CostsBundle\Entity\Item') {
return '';
}
$fdata = $this->getParameter('deleted');
$filter = '1<>1';
foreach ($fdata as $param) {
$filter .= sprintf('OR %s.deleted = %s', $targetTableAlias, $param);
}
return $filter;
}
}
But when I'm trying to set array of posible filter values in controller
$filters
->enable('costs_item_deleted')
->setParameter('deleted', [true, false]);
I get an error 500
Warning: PDO::quote() expects parameter 1 to be string, array given
This is clear situation. But, after all HOW to send array of params to my SQL filter?
UPD after Dmitry answer: This is not actualy what I wanted. Let say: what if I wanted to filter by few values of field? For records of 2015 and 2016 years for example... So i need to set some sort of array-of-years in ->setParameter. But it want only strings! And sends an error when i'm trying to set something else.
How do you solve this?
Or even more complicated example. What if I need to filter by relational field. In this case I need to set entity as param of filter. Or even ArrayCollection of entities!
For now I'm decide it like this: I json_encode array before set it to setParameter in controller. And then I json_decode it in Filter class. BUT! There in Filter class I need to make one more step. I need to remove single and doublequotes from json string. Because they was added by setParameter to escape string (thats why we love it )) ).
Code hacks like this we call "crutches" here in Russia. So I'd like to avoid of them and write more elegant code )
Make it IN instead of comparing.
foreach ($fdata as $param) {
$filter .= sprintf('OR %s.deleted IN (%s)', $targetTableAlias, param);
}

How to remove galleryhasmedia from gallery sonatamediabundle

I am trying to remove galleryhasmedia from gallery.
However gallery entity doesn't have removegalleryhasmedia or something.
so I did a clumsy way, but it doesnt work.
$em = $this->getDoctrine()->getManager();
$firstGhmArray = $gallery->getGalleryHasMedias();
echo count($gallery->getGalleryHasMedias()) // before count
$afterGhmArray = array();
foreach ($firstGhmArray as $ghm){
if ($ghm->getId() == $id){ // id is the target id to delete
//delete
}
else {
array_push($afterGhmArray , $ghm);
}
$gallery->setGalleryHasMedias($afterGhmArray);
}
echo count($gallery->getGalleryHasMedias()) // after count
$em->persist($gallery);
$em->flush();
I think if galleryHasMedias are normal array collection.
I can delete the element with this procedure.
I need to do something more for galleryhasmedia??
You can override the Gallery entity and add this function to it :
public function clearGalleryHasMedias()
{
$this->galleryHasMedias->clear();
}
galleryHasMedias field is an ArrayCollection which can be cleared using the clear method. Its weird tho that setting an empty array doesn't clear work but i guess my solution is worth the shot.

Remove entity from post before binding it

Let's say I have a main form (foo entity form) where I have an embedded form (bar entity embedded form).
Let's also say that foo - 1/many - bar (of course).
Now, I want to display all possible bar entities in the system, even if they aren't associated with foo. So before bind form with foo entity, I usually do some query, extract data and, if bar isn't already associated with foo, associate it (basically i create some "virtual" association that haven't to be persisted under certain circumstance. I can't use symfony2 native method as I need to handle some attributes and Symfony2 don't let me do that)
All works like a charm. Now I added to bar form a non-mapped field that should help me to know whenever to save or not the association.
Into controller I check for the presence of this field and if not, I artificially unset the index of the collection from request object. When I dump the request all is good (embedded elements without flag aren't there anymore).
BUT
When I bind request object to entity, all embedded form elements are still there. This is driving me totally cray.
Code example
(I will not paste entity code as the issue is not there. I will not paste form code also)
public function createAction()
{
$foo = new Foo();
$foo_form = $this->createForm(new FooType(), $foo);
if ($request->getMethod() == 'POST') {
$parameter_array = $request->request->all();
$bar_array = $parameter_array['foo']['bar'];
//If I dump here, of course, all bar are setted
foreach ($bar_array as $index => $bar) {
if (!isset($bar['associate'])) { //this is the flag
unset($parameter_array['foo']['bar'][$index]);
}
}
$request->request->replace($parameter_array);
//If i dump $request->request->all(); all non-flagged bar are gone
$foo_form->bind($request);
$foo->getBars(); //If I dump this all bar(s) are still there (even the not-flagged ones)
}
}
I've found a workaround. As I can't controller - or at least it seems I cannot - directly parameter bag when entities are involved, I've simply act upon object after form and object are binded.
My code is now this
public function createAction()
{
$foo = new Foo();
$foo_form = $this->createForm(new FooType(), $foo);
if ($request->getMethod() == 'POST') {
$foo_form->bind($request);
if ($foo_form->isValid()) {
$parameter_array = $request->request->all();
if (isset($parameter_array['foo']['bar'])) {
$bars = $foo->getBars();
$bar_array = $parameter_array['foo']['bar'];
foreach ($bar_array as $index => $bar) { //Of course here
if (!isset($bar['associate'])) { // I can use array_filter
$bars->remove($index); // or something similar. Is just more readable that way for this answer
}
}
$foo->setBars($bars);
}
}
}
}
Is there a better solution?

How to display LONGBLOB field data in TWIG file

I am working in Symfony2. I have a field in table that uses LONGBLOB. So now I want to display field data.When I display this LONGBLOB field data it show's me text like this
Resource id #404 but actually in field I have stored the dummy text.
This is my defaultcontrolle file code
DefaultController.php
function video_showAction($id)
{
$em = $this->getDoctrine()->getManager();
$video = $em->getRepository('MyBundle:Video')->find($id);
return $this->render('MyBundle:Default:VideoShow.html.twig', array('qShow' => $video ));
}
VideoShow.html.twig
Description: {{ qShow.description }}
// it will display "Resource id #404"
How can I display the actual data not he Refrence.
As you mentioned in your own answer, you should rewrite your getter function.
I propose something like that:
private $descriptionAsText = null;
public function getDescription()
{
if (is_null($this->descriptionAsText))
{
$this->descriptionAsText = stream_get_contents($this->description);
}
return $this->descriptionAsText;
}
If your stream can change in the same instance of the entity, you can eventually use:
public function getDescription()
{
rewind($this->description);
return stream_get_contents($this->description);
}
I dislike your current method, as if you need to use {{ qShow.description }} twice or more, you will get troubles because of your stream offset.
You need to rewind your resource each time you're doing a stream_get_contents, because it places the offset at the end of your stream (or at the specified length).
You can reproduce this behavior using the following code:
<?php
file_put_contents("/tmp/test.txt", "Hello, world!");
$handle = fopen("/tmp/test.txt", "r");
$contents = stream_get_contents($handle);
echo "Contents A = {$contents}\n"; // Contents A = Hello, world!
$contents = stream_get_contents($handle);
echo "Contents B = {$contents}\n"; // Contents B =
fclose($handle);
This behaviour is there since PHP 5.3 (I guess), so if you try this code on Codepad (who uses 5.2.5), you will not reproduce.
I have found the Solution.
I just need to use stream_get_contents. So I have put this into Getter method of my Entity.
Like this
MyEntity.php
// Getter Function need to be change like this
public function getDescription()
{
if ($this->description != '')
return stream_get_contents($this->description);
return $this->description;
}
Now When I display the content it shows me the Actual Data that the Recourse Id contains.
For using LONGBLOB firs you need do the following works. this works are describe in detail at the following link please check that you do all of them and then try again to show your qShow.description on your twig file. I think "Resource id #404" error say you that you have problem reading your resource with 404 ID Number.
http://symfony2.ylly.fr/add-new-data-type-in-doctrine-2-in-symfony-2-jordscream/

Silverstripe bulk save all dataobjects

I've added URLSegments to DataObjects (Products) so I can then display the ProductName as the URL....the code works fine:
public function onBeforeWrite(){
if($this->Name){
$this->URLSegment = SiteTree::GenerateURLSegment($this->Name);
if($object = DataObject::get_one($this->ClassName, "URLSegment='".$this->URLSegment."' AND ID !=".$this->ID)){
$this->URLSegment = $this->URLSegment.'-'.$this->ID;
}
} else {
$this->URLSegment = SiteTree::GenerateURLSegment($this->ClassName.'-'.$this->ID);
}
parent::onBeforeWrite();
}
But, I have over 1000 Products...is there any way of generating a bulk save for all Product Dataobjects in code (ie as a one-off) so I don't have to manually save each through the CMS??
Just create a controller with an index function and use more or less the same code.
<?php
class UpdateProducts extends Controller {
public function index() {
$products = DataObject::get('Products');
foreach ($products as $product) {
if (!$product->URLSegment) {
$product->write();
}
}
}
}
Then you can call the function once from the browser at http://example.com/UpdateProducts
This isn't super efficient so it really is only a one off. If the script times out, you can just run it again as the if statement in there means only products without a URLSegment will be updated.
I started to implement drzax solution, then found this, which implements it as a task. This task was created to add URLSegments to products, so fits my needs perfectly...
http://www.balbuss.com/creating-tasks/

Resources