paginationpositionsilverstripedata-objects

Silverstripe 4 PaginatedList get Page-number - Link (Backlink)


In Silverstripe 4 I have a

PublicationObjects are displayed on PublicationPage through looping a PaginatedList. There is also a Pagination, showing the PageNumbers and Prev & Next - Links.

The Detail of PublicationObject is shown as 'Dataobject as Pages' using the UrlSegment.

If users are on the Detail- PublicationObject i want them to get back to the PublicationPage (the paginated list) with a Back - Link.

Two situations:

and

I have done this like so:

$parentPage = Page::get()->Filter(array('UrlSegment' => $request->param('pageID')))->First();
        
        $back = $_SERVER['HTTP_REFERER'];
        if ((isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER']))) {
            if (strtolower(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)) != strtolower($_SERVER['HTTP_HOST'])) {
                // referer not from the same domain
                $back = $parentPage->Link();
            }
        }

Thats not satisfying.

Question:

How do i get the Pagination - Link ( e.g: ...publicationen?start=20 ) when we are on the Detail - DataObject? How can we find the Position of the current Dataobject in that paginatedList in correlation with the Items per Page? (The Page- Link This Dataobject is on)

<?php

use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\View\Requirements;
use SilverStripe\Core\Convert;
use SilverStripe\SiteConfig\SiteConfig;
use SilverStripe\ORM\PaginatedList;
use SilverStripe\Control\Director;
use SilverStripe\ORM\DataObject;
use SilverStripe\ErrorPage\ErrorPage;
use SilverStripe\Dev\Debug;
use SilverStripe\Dev\Backtrace;

class PublicationPageController extends PageController
{
    
    private static $allowed_actions = ['detail'];
    
    private static $url_handlers = array(
    );
    
    public static $current_Publication_id;
    
    public function init() {
        parent::init();
    }
    
    public function detail(HTTPRequest $request)
    { 
        
        $publication = PublicationObject::get_by_url_segment(Convert::raw2sql($request->param('ID')));
        
        if (!$publication) {
            return ErrorPage::response_for(404);
        }
        
        
        
        // HERE I WANT TO FIND THE POSITION OF THE DATAOBJECT IN THE PAGINATEDLIST OR RATHER THE PAGE - LINK THIS DATAOBJECT IS IN
        //$paginatedList = $this->getPaginatedPublicationObjects();
        //Debug::show($paginatedList->find('URLSegment', Convert::raw2sql($request->param('ID'))));
        //Debug::show($paginatedList->toArray());
        
        
        $parentPage = Page::get()->Filter(array('UrlSegment' => $request->param('pageID')))->First();
        
        $back = $_SERVER['HTTP_REFERER'];
        if ((isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER']))) {
            if (strtolower(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)) != strtolower($_SERVER['HTTP_HOST'])) {
                // referer not from the same domain
                $back = $parentPage->Link();
            }
        }
        
        static::$current_Publication_id = $publication->ID;
        $id = $publication->ID;
        
        if($publication){
            $arrayData = array (
                'Publication' => $publication,
                'Back' => $back,
                'SubTitle' => $publication->Title, 
                'MetaTitle' => $publication->Title, 
            );
                
            return $this->customise($arrayData)->renderWith(array('PublicationDetailPage', 'Page'));

        }else{
            return $this->httpError(404, "Not Found");
        }
    }
    
    
    
    public function getPaginatedPublicationObjects()
    {
        
        $list = $this->PublicationObjects()->sort('SortOrder');
        return  PaginatedList::create($list, $this->getRequest()); //->setPageLength(4)->setPaginationGetVar('start');
        
    }
    
}

EDIT:

is there a more simple solution ? than this ? :

public function detail(HTTPRequest $request)
    { 
        
        $publication = PublicationObject::get_by_url_segment(Convert::raw2sql($request->param('ID')));
        
        if (!$publication) {
            return ErrorPage::response_for(404);
        }
        
        //*******************************************************
        // CREATE BACK - LINK 
        $paginatedList = $this->getPaginatedPublicationObjects();
        $dO = PublicationObject::get();
        $paginationVar = $paginatedList->getPaginationGetVar();
        
        $sqlQuery = new SQLSelect();
        $sqlQuery->setFrom('PublicationObject');
        $sqlQuery->selectField('URLSegment');
        $sqlQuery->setOrderBy('SortOrder');
    
        $rawSQL = $sqlQuery->sql($parameters);

        $result = $sqlQuery->execute();
        $list = [];
        foreach($result as $row) {
            $list[]['URLSegment'] = $row['URLSegment'];
        }
        
        $list = array_chunk($list, $paginatedList->getPageLength(), true);
        $start = '';
        $back = '';
        $i = 0;
        $newArray = [];
        foreach ($list as $k => $subArr) {
            $newArray[$i] = $subArr;
            unset($subArr[$k]['URLSegment']);
            foreach ($newArray[$i] as $key => $val) {
                if ($val['URLSegment'] === Convert::raw2sql($request->param('ID'))) {
                    $start = '?'.$paginationVar.'='.$i;
                }
            }
            $i = $i + $paginatedList->getPageLength();
        }
        
        $back = Controller::join_links($this->Link(), $start);
        // END CREATE BACK - LINK
        //*****************************************************

        static::$current_Publication_id = $publication->ID;
        $id = $publication->ID;
        
        if($publication){
            $arrayData = array (
                'Publication' => $publication,
                'Back' => $back,
                'MyLinkMode' => 'active',
                'SubTitle' => $publication->Title, 
                'MetaTitle' => $publication->Title, 
            );
            return $this->customise($arrayData)->renderWith(array('PublicationDetailPage', 'Page'));
            
        }else{
            
            return $this->httpError(404, "Not Found");
        }
    }

Solution

  • You can simply pass the page number as a get var in the URL from the PublicationPage. The detail() method can then grab the get var and if there's a value for the page number passed in, add it to the back link's URL.

    In the template:

    <% loop $MyPaginatedList %>
        <a href="$Link?onPage=$Top.MyPaginatedList.CurrentPage">Click me</a>
    <% end_loop %>
    

    In your controller's detail() method:

    $pageNum = $request->getVar('onPage');
    if ($pageNum) {
        // Add the pagenum to the back link here
    }
    

    Edit

    You've expressed that you want this to use the page start offset (so you can just plug it into the url using ?start=[offset]), and that you want an example that also covers people coming in from outside your site. I therefore propose the following:

    Do as above, but using PageStart instead of CurrentPage - this will mean you don't have to re-compute the offset any time someone clicks the link from your paginated list.

    If there is no onPage (or pageOffset as I've renamed it below, assuming you'll use PageStart) get variable, then assuming you can ensure your SortOrder values are all unique, you can check how many items are in the list before the current item - which gives you your item offset. From that you can calculate what page it's on, and what the page offset is for that page, which is your start value.

    public function detail(HTTPRequest $request)
    { 
        $publication = PublicationObject::get_by_url_segment(Convert::raw2sql($request->param('ID')));
        $paginatedList = $this->getPaginatedPublicationObjects();
    
        // Back link logic starts here
        $pageOffset = $request->getVar('pageOffset');
        if ($pageOffset === null) {
            $recordOffset = $paginatedList->filter('SortOrder:LessThan', $publication->SortOrder)->count() + 1;
            $perPage = $paginatedList->getPageLength();
            $page = floor($recordOffset / $perPage) + 1;
            $pageOffset = ($page - 1) * $perPage;
        }
        $back = $this->Link() . '?' . $paginatedList->getPaginationGetVar() . '=' . $pageOffset;
        // Back link logic ends here
        //.....
    }