Wednesday, September 09, 2009

Fixing default cakePHP pagination in FBML

CakePHP pagination generates relative URLs that look like

/posts/view/page:5

when you use

$paginator->prev()
$paginator->numbers()
$paginator->next()

This doesn't work in FBML, so you need to sort of hack the PaginatorHelper to display it as

http://apps.facebook.com/someapp/posts/view/page:5

So you change function link() to

function link($title, $url = array(), $options = array()) {
        $options = array_merge(array('model' => null, 'escape' => true), $options);
        $model = $options['model'];
        unset($options['model']);

        if (!empty($this->options)) {
            $options = array_merge($this->options, $options);
        }
        if (isset($options['url'])) {
            $url = array_merge((array)$options['url'], (array)$url);
            unset($options['url']);
        }
        if(!isset($_SERVER['HTTP_X_FB_USER_REMOTE_ADDR']) ) {
            $url = $this->url($url, true, $model);
            $obj = isset($options['update']) ? 'Ajax' : 'Html';
            $url = array_merge(array('page' => $this->current($model)), $url);
            $url = array_merge(Set::filter($url, true), array_intersect_key($url, array('plugin'=>true)));
        } else {
            //if its part of the facebook app, preprend http://apps.facebook.com/dev_zenmanga to the $url
            $obj = isset($options['update']) ? 'Ajax' : 'Html';
            $url = 'http://apps.facebook.com/someapp' . substr(parent::url($url), true);
        }
        return $this->{$obj}->link($title, $url, $options);
    }

$_SERVER['HTTP_X_FB_USER_REMOTE_ADDR']
will print out the server IP that your facebook app is hosted on, so if that is set, then we know we are running on the facebook server.

A better way will be to write in your config/bootstrap.php

if(isset($_SERVER['HTTP_X_FB_USER_REMOTE_ADDR'])){
        Configure::write('App.base', 'http://apps.facebook.com/someapp/');
    }