Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Design Critiques Requested - Remote Content Wrapper Page


Reply


1140 Views

Avatar
Ben Gribaudo

Community Member, 181 Posts

20 May 2009 at 4:15am

Edited: 20/05/2009 4:17am

Hello,

I am working on a custom page type that allows a remote web resource (say, a forum) to be mounted in a SilverStripe site. To the end user, the mounted resource looks and feels like it is apart of the SS site (consistent template and navigation).

Example:
If the wrapper page is inserted at http://mysite/mount/ and is set to wrap content from http://othersite/forum/, a request for http://mysite/mount/page1/ will be forwarded to http://othersite/forum/page1/. When content is received back from othersite, the page wraps that content in the appropriate SS template.

Would you have time to critique this code?

In particular, some thoughts/questions I have:

  • In WrapperPage's Children() method, how do I set the Page's URL?
  • Do I need to define stageChilden() and liveChildren() in WrapperPage?
  • In case you're wondering, I would like to eliminate the multiple calls to $this->loadRemotePage() by calling it once from WrapperPage's constructor, however, when I define a __construct() method on WrapperPage, the PHP script hangs. I have yet to debug this problem.
  • Is there a way to eliminate the overriding of handleAction in the controller? Right now, without that override, only requests for http://mysite/mount/ will work. Requests for pages like http://mysite/mount/page1/ will return a not-found error.

FYI, I'm developing against nestedurls.

Thank you,
Ben

<?php
// Code by: Ben Gribaudo - www.bengribaudo.com
require_once 'HTTP/Request.php';

class WrapperPage extends Page {
   public static $db = array(
      'SourceURL' => 'Varchar(500)',
      'ContentSelector' => 'Varchar(100)'
   );
   public static $has_one = array();
   public static $allowed_children = array();
   private $remotePageLoaded = false;
   
   public function getCMSFields() {
      $fields = parent::getCMSFields();
      $fields->removeFieldFromTab("Root.Content.Main", "Title");
      $fields->removeFieldFromTab("Root.Content.Main", "Content");
      $fields->addFieldToTab('Root.Content.Main', new TextField('SourceURL', 'Source URL (No Query Strings)'));
      $fields->addFieldToTab('Root.Content.Main', new TextField('ContentSelector', 'Content Selector (XPath)'));
      return $fields;
   }
   
   public function onBeforeWrite() {
      $this->Title = $this->MenuTitle;
      return parent::onBeforeWrite();
   }

   public function Children() {
      $this->loadRemotePage();
      $children = new DataObjectSet();
      foreach ($this->Children as $childTitle => $childLink) {
         $page = new Page();
         $page->Title = $childTitle;
         // Doesn't work!
         //$page->URL = $this->Link() . $childLink;
         $children->push($page);
      }
      return $children;
   }

   public function Title() {
      $this->loadRemotePage();
      return $this->Title;
   }
   
   public function Content() {
      $this->loadRemotePage();
      return $this->Content;
   }   
   
   private function loadRemotePage() {
      if (!$this->remotePageLoaded) {
         $currentURL = '/' . $this->CurrentPage()->request->getVar('url');
         if (preg_match('/^' . preg_quote($this->Link(), '/') . '/i', $currentURL)) {
            $subUrl = str_ireplace($this->Link(), '', $currentURL);
         } else {
            $subUrl = '';
         }
         
         $remotePage = new RemotePage(new WebPageLoader(new HTTP_Request()), $this->SourceURL, $this->Link(), create_function('$url', 'header("Location: $url"); exit();'), create_function('$cookie, $expires', 'setcookie($cookie["name"], $cookie["value"], $expires, $cookie["path"]);'));
         $xPathDoc = $remotePage->load($subUrl, $_GET, $_POST, $_COOKIE);
         $this->Title = $xPathDoc->queryFirstAsHTML('/html/head/title');
         $this->Content = $xPathDoc->queryFirstAsHTML($this->getField('ContentSelector'));
         // children eventually will be populated from data contained in the xPathDoc
         $this->Children = array('Topic1' => 'topic1', 'Topic2' => 'topic2');
         $this->remotePageLoaded = true;
      }
   }
}

class WrapperPage_Controller extends Page_Controller {
   // $action parameter is ignored
   public function handleAction($action) {
      try {
         return $this->renderWith($this->getViewer('index'), $this->dataRecord);
      } catch (RemotePageLoadError $exception) {
         return $this->httpError(500, '500 Internal Server Error');
      }
   }
}
?>