Search code examples
cachingsilverstripecache-manifest

UPDATE: Updating manifest cache version and date in SilverStripe on upload


I'm working on trying to dynamically append new image files to a cache manifest file for a SilverStripe site. I have the beginnings of a function that is currently holding all the current files I need cached:

class HomePage_Controller extends ContentController {

private static $allowed_actions = array (
    "UpdateManifest"
);

public function UpdateManifest() {

        $static = <<<EOT
CACHE MANIFEST
#$ManifestDate $ManifestVersion
#all javascript/jquery files currently added

#css files currently added

#image files currently added
EOT;

        $static = $static . "\n" . "/test.html";
        $this->response->addHeader("Content-type", "text/cache-manifest");
        return $static;
    }
}

I want to append the new image files uploaded in the SilverStripe admin to the $static variable. I need to build out the image tags in a certain way, though, since the images are pulled from Youtube thumbnails. I have an admin model called VideoLinkIDs, which has a field called VideoID that takes the Youtube video id. I need to somehow find a way to build out a list of images with this sort of image tag setup:

 <img class='vidThumb' src='http://img.youtube.com/vi/".VideoID."/0.jpg />

I have managed to make some progress with this (finally), and here is what I have: I created a CacheManifest class that is going to hold the current date and the version number variables (these will be used to update the version and date inside the $static variable in the UpdateManifest function from above).

<?php

class CacheManifest extends DataObject {

    private static $db = array(
        'CurrentDate' => 'Date',
        'VersionNumber' => 'int'
    );

    private static $summary_fields = array(
        'ID' => 'ID',
        'CurrentDate' => 'Current Date',
        'VersionNumber' => 'Version Number'
    );

    public function updateCache(){
        $currentDate = SS_Datetime::now();
        $versionNumber = 1;

        $this->CurrentDate = $currentDate;
        $this->VersionNumber = //increment the value currently stored in the database

        $this->write();
    }
}

This updateCache function is then called in the class file for the VideoLinkID's onAfterWrite() method so that the database is updated every time a new video ID is saved in the admin:

 public function onAfterWrite(){
    $updateGallery = parent::getCMSFields();

    //get the entry from the CacheManifest database
    CacheManifest::get()->(get VersionNumber and CurrentDate from database?)
    return $updateGallery;
}

What I want to do with updateCache is increment the VersionNumber by 1 every time there is a new video id added (with SilverStripe syntax, I'm a little confused on how to do that part). I don't want to add a new entry to the CacheManifest table every single time I upload a video--I just want to keep updating the first entry.

EDIT: The relationship between the CMS and the youtube video ids is this: The page template type has a tab called "Video IDs" where a content manager can paste any number of youtube video ids. These ids are then used to grab the youtube video preview thumbnails. These thumbnails are displayed in a gallery popup modal for users to see and click on to view the full length videos.

This site is going to need a cache manifest file to ensure that, at the very least, the users will be able to still view the youtube preview thumbnails when they view the gallery. Seeing as how the standard method of maintaining a cache manifest is to manually update it, this would not be ideal as a developer would need to constantly keep updating the site's cache manifest as the content manager adds in youtube video ids (there is no knowing how many youtube video ids there will be at all time)

A dynamic cache manifest file would be very useful in this case, something that would update the date and version number with each video id added to a page template in the CMS. Hence the existence of the CacheManifest data object class. This class stores the current date and an int inside the updateCache() function. This function should somehow be called in onAfterWrite() in the VideoLinkID class.

None of this was my idea, it was formulated by another developer and this seems to be what I have to go with. To be honest, I would rather find a better way but I have not found anything that has been approved of, and no one else I know has, either. This is all quite new and definitely not the norm.


Solution

  • Here is an example of how you may implement something similar.

    Video object that stores video hashes

    class GalleryVideo extends DataObject {
        private static $db = array(
            'Name' => 'Varchar(255)',
            'VideoHash'  => 'Varchar(16)'
        );
    
        public function getThumbLink() {
            return 'http://img.youtube.com/vi/' . $this->VideoHash . '/0.jpg';
        }
    }
    

    Template that uses cache manifest, /themes/simples/templates/GalleryPage.ss

    <html manifest="gallery-appcache">
    ...
    </html>
    

    Cache manifest page

    class GalleryCacheManifest extends SiteTree {
        private static $db = array(
            'Version' => 'Int',
        );
    
        private static $has_many = array(
            'Videos' => 'GalleryVideo',
        );
    
        public functon getCMSFields() {
            $fields = parent::getCMSFields();
            $fields->addFieldToTab('Root.Main', NumericField::create('Version'));
            $fields->addFieldToTab('Root.Main', TextField::create('Content', 'Cached files')->setRows(20));
            $fields->addFieldToTab('Root.Videos', GridField::create('Videos'));
            return $fields;
        }
    
        // Override actions to Save & Publish always.
        public function getCMSActions() {
            $actions = parent::getCMSActions();
            $actions->removeByName('action_save');
            return $actions;
        }
    
        public functon requireDefaultRecord() {
            if (0 < Versioned::get_by_stage('GalleryCacheManifest', 'Stage')->count()) {
                return;
            }
    
            $page = new GalleryCacheManifest();
            $page->Title = 'gallery-appcache';
            // URL in the http request is split into segments, and extension does not count, so gallery.appcache is wrong
            $page->URLSegment = 'gallery-appcache';
            $page->ShowInMenus = false;
            $page->ShowInSearch = false;
            $page->AuthorID = 1; // Default Admin
            $page->write();
    
            $page->publish( 'Stage', 'Live' );
            $page->flushCache();
            DB::alteration_message( 'GalleryCacheManifest created', 'created' );
    
        }
    
        public functon canCreate($member = null) {
            return 0 === Versioned::get_by_stage('GalleryCacheManifest', 'Stage')->count();
        }
    
        public function canDelete($member = null) {
            return false;
        }
    }
    
    class GalleryCacheManifest_Controller extends ContentController {
        public functon index(SS_HTTPRequest $request) {
            $this->getResponse()->addHeader( 'Content-Type', 'text/cache-manifest' );
        }
    }
    

    Template file: themes/simple/templates/GalleryCacheManifest.ss:

    CACHE MANIFEST
    # $LastEdited.Format('Y-m-d'):$Version
    
    CACHE:
    $Content
    <% if $Videos.Count %>
    <% loop $Videos %>
    $ThumbLink
    <% end_loop %>
    <% end_if %>
    
    NETWORK:
    *