0
votes

I am using the blog module with SilverStripe and I am trying to call all widgets from the parent (blog holder) page on the blog entry page. I have created a function which runs in the BlogEntry.php file. This function gets the parent page, gets the widgets associated with it and I now have access to the widget information.

function getParentWidgets() {
        $Holder = DataObject::get_by_id('Page', $this->ParentID);
        if (isset($Holder->MyWidgetAreaID)) {
            $WidgetArea = $Holder->MyWidgetAreaID;
        }

        $Widgets = DataObject::get('Widget');
        $parentWidgets = new ArrayList();
        foreach ($Widgets as $Widget) {
            if ($Widget->ParentID == $WidgetArea) {
                $parentWidgets->push($Widget);
            }
        }

        foreach ($parentWidgets as $widget) {
            error_log($widget->ID);
        }

        return $parentWidgets;
    }

The error log within there returns the following

[Tue Jul 07 13:51:01 2015] [error] [client 10.0.2.2] 4

[Tue Jul 07 13:51:01 2015] [error] [client 10.0.2.2] 5

[Tue Jul 07 13:51:01 2015] [error] [client 10.0.2.2] 6

[Tue Jul 07 13:51:01 2015] [error] [client 10.0.2.2] 7

I have access to this information but how would I loop over this in the template and show the widget in full? Currently if i loop and within the loop i enter a random string of text such as 'foo' it will display that four times over.

<% with $getParentWidgets %>
    foo
<% end_with %>

I just need to show the whole widget itself.. is there a way to do that?

Thanks, if you need anything more let me know.

2

2 Answers

2
votes

The SS template equivalent to $this is $Me. That will display the object in the current scope, provided it's capable of being rendered.

Another option is to form your ArrayList with an associative array; you can then use the key to retrieve the value from within the loop.

In this case, I'd probably recommend $Me. You'll also want to loop over the results, rather than just changing the context with 'with'. The 'get' prefix is optional since your function doesn't require arguments.

<% loop $ParentWidgets %>
    $Me
<% end_loop %>

If this is SS3, you should update your ORM retrievals.

$Holder = DataObject::get_by_id('Page', $this->ParentID);

Is now:

$Holder = Page::get()->byID($this->ParentID);

And

$Widgets = DataObject::get('Widget');

is now

$Widgets = Widget::get();
0
votes

I managed to get this working.

function getParentWidgets() {
        $Holder = DataObject::get_by_id('Page', $this->ParentID);
        if (isset($Holder->MyWidgetAreaID)) {
            $WidgetArea = $Holder->MyWidgetAreaID;
        }

        error_log($Holder);

        $Widgets = Widget::get();
        $parentWidgets = new ArrayList();
        foreach ($Widgets as $Widget) {
            if ($Widget->ParentID == $WidgetArea) {
                $renderedWidget = $Widget->renderWith('WidgetHolder');
                $parentWidgets->push($renderedWidget);
            }
        }

        return $parentWidgets;
}

As you can see I retrieved the parent Blog Holder page. Within an if I checked that the widget area id was set for that page. I then saved that widget area ID within a variable called WidgetArea.

I retrieved every widget in the DB and created an arrayList ready for population. I looped over all of the widgets and checked their parentIDs, if the parentID was a match to the BlogHolder widget area I would push them in the array. This meant all of the widgets in the array were widgets of the BlogHolder page.

Note that I stored the rendered version of each of the widgets as I couldn't render in a loop. I then returned the parentWidgets ArrayList to the template.

Within the template I then looped over what was returned so I could read all widgets.

<% loop $getParentWidgets %>
        $value
<% end_loop %>

In the loop I called $value. You could have also called $Me to achieve the same outcome.