Nov 27, 2010
admin

The detail page

To implement the detail page, we will basically redo what we have done for the index page. One thing we will not redo it, however, is the template section. This will work for all the views.
So, let’s start with the controller and add the detail action.

    /**
     * Detail action
     *
     */
    public function detailAction()
    {
        if (!isset($this->Request['id']) || !is_numeric($this->Request['id']))
        {
            $this->Router->redirect('index');
        }
        $this->model->id = $this->Request['id'];
        $this->model->checkin();
        if (!isset($this->model->id) || empty($this->model->id))
        {
            $this->Router->redirect('index');
        }
        $this->view->feed = new stdClass();
        $this->view->feed->name  = $this->model->name;
        // get the rss feeds
        $this->getFeedInfos($this->view->feed, $this->model->url, $this->model->itemsNumber);
    }

The detail Action is supposed to get a feed id from the request, sot before getting the feeds, we verify if everything is okay with that parameter, and we also check if there is a
model corresponding to that id. This is done by affecting the id to the model and by calling the checkin method. This method will fill the object properties with the relative field if the id exists in the database. If the record is not found, the model properties remain empty and the id property we previously affected will be cleared also. That’s why we are checking on the id after the checkin call.
If the id does not exist, using the Router object, we can redirect the user using the redirect method. If the record exists, we will get the feed from the private method getFeedInfos to which we give three parameters: $this->view->feed: this will be where the feeds are stored. the url from the model, and the items number we want to retreive.

So let’s code that method :

    /**
     * Returns a list of elements from an rss Feed
     *
     * @param  mixed  $url
     * @param  int    $itemsNumber
     * @return array the rss items
     */
    private function getFeedInfos($feed, $url, $itemsNumber)
    {
        $rss = $this->getRSS($url, $itemsNumber);
        $feed->title = $rss->channel->title;
        $feed->description = $rss->channel->description;
        $feed->link = $rss->channel->link;
        $feed->lastUpdated = $rss->channel->lastBuildDate;
        $feed->image = $rss->channel->image;
        $feed->items = array();
        $i = 0;
        foreach ($rss->channel->item as $item)
        {
            if ($i == $itemsNumber) break;
            $feed->items[] = $item;
            $i++;
        }
    }
 
    /**
     * gets a feed
     *
     * @param  mixed  $url
     * @param  int    $itemsNumber Optional, defaults to 5.
     * @return SimpleXMLElement the element
     */
    private function getRSS($url, $itemsNumber = 5)
    {
        $feedKey = 'simplemvc_cache_feeds_list_' . $url;
        if (!$this->CacheManager->exists($feedKey))
        {
            $client = new CurlClient();
            $client->setUrl($url);
            $client->setReturnTransfer(true);
            $client->setAsGet();
            $feedRaw = $client->call();
            $this->CacheManager->set($feedKey, $feedRaw, $this->Config['general']['rss']['ttl']);
            $feeds = simplexml_load_string($feedRaw);
        }
        else
        {
            $feeds = simplexml_load_string($this->CacheManager->get($feedKey));
        }
        return $feeds;
    }

Okay, time to explain what we did. The getFeedInfo method will get the information from the getRSS method and fill only the information we need in the view from the result. nothing more to say for that method. However, it is in the getRSS method where things are done.
This method uses a cache mechanism. to implement that, we need to define a unique cache key : $feedKey. To check if there is the rss has been already checked before we use the exists method of the CacheManager. if it is the case, we use the get method to get the content.
If this is the first time we ask for this RSS, we will do a curl call to get the contents and store them in the cache by the occasion. We make use of the CurlClient class to get the contents. setURl, setReturnTransfer, setAsGet and call are self explanatory. Next, the CacheManager->set method stores the entry in the cache, and we affect a SimpleXMLElement to the $feeds variable.
We will do some refactoring later on to get out the CurlClient instanciation from the controller. if We want a unit testable code, we should not have instanciations directly in the controller. The CurlClient will be moved to the Container. we will cover that later.
This is all we need to do for the controller, Let’s code the view part. open a new file business/front/views/Feed/detail.php and add the following:

<div class="ui-grid-a">
    <?php if (!empty($this->feed->image->url)) { ?>
    <div class="ui-block-a">
        <a href="<?php echo $this->feed->link?>">
            <img src="<?php echo $this->feed->image->url?>" alt="<?php echo $this->feed->image->title?>" title="<?php echo $this->feed->image->title?>"/>
        </a>
    </div>
    <?php } ?>
    <div class="ui-block-b">
    <h3>
        <a href="<?php echo $this->feed->link?>">
            <?php echo $this->feed->title?>
        </a><br/>
        <?php echo $this->languages['last_updated'] . ' : ' . $this->feed->lastUpdated?>
    </h3>
    </div>
</div>
<div data-role="collapsible">
    <h3><?php echo $this->languages['you_are_reading_feed'] . ' : ' . $this->feed->name ?></h3>
    <?php
    if (!count($this->feed->items))
    {
        ?><div class="feed_element"><?php echo $this->languages['no_feed_entries']?></div><?php
    }
    else
    {
        foreach ($this->feed->items as $item)
        {
            ?>
                <div class="feed_element">
                <h4><a href="<?php echo $item->link?>"><?php echo $item->title?></a></h4>
                <p><?php echo $item->description ?></p>
                </div>
                <?php
        }
    }
    ?>
</div>

This follows same rules, looping through items to display the items information, using the language variables when needed. We already added the languages for the feed.detail page in the business/front/conf/languages.en.ini file.
Finished : Let’s test the page!, click on a feed and you should see the details with a nice sliding effect.
Let’s move forward to add an action that adds a feed.

Leave a comment