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.

Data Model Questions

Saving image from URL without CMS field


Reply

4 Posts   3712 Views

Avatar
J

8 June 2010 at 12:07pm Community Member, 3 Posts

Hi,

i am trying to save an image dynamically from Vimeo for a website I'm making.

Currently I have set up the CMS so you can input a Video ID. The Video ID is then used with Restful Service to get the XML of its associated data. One piece of data is a URL to the video's thumbnail.

Is there a way get the image from this URL, save it to my assets/uploads and save it to the database as a has_one image? Similar to what the imageField does but without the user upload and the actual field.

Any help is much appreciated.

J

Avatar
nostradamus1935

11 June 2010 at 8:57am Community Member, 9 Posts

It looks pretty much like what I'm doing, except I'm making a thumbnail from a local pdf. The idea, that I got from FLV.php in DataObjectManager, goes like this :

1. you make the file and save it in a predictable place. I used imagemagick, FLV.php uses ffmpeg in createThumbnail(), you would probably use wget with exec() .

2. Use something like this :

$img = new Image();
$img->setField('ParentID',$folder->ID);
$img->Filename = $folder->Filename.$img_filename;
$img->Title = $img_title;
$img->write();

3. Then, in a function called onBeforeWrite() in your DataObject you do something like :
$this->ImageId = DataObject::get('Image', ...with the attributes you gave it like a predictable name or something similar... )->ID;

I'm not sure this is the proper or best way to do it, but I'm pretty sure it would work ok. It works for me, actually, my pdf thing. The hardest part was to get the filenames and paths right in the command line. Had to output them a few times before I got them right...

Hope that helps. :-)

Avatar
J

12 June 2010 at 2:32am (Last edited: 12 June 2010 2:34am), Community Member, 3 Posts

Thanks heaps nostradamus1935. You put me on the right track. I made some slight changes to the way you went about doing it. I checked out FileIframeField to get the ideas of how to save an image to the database then assign it to a dataobjects has_one relationship.

The basic idea here was to have a field that you input a vimeo video ID into and it will grab the video's thumbnail. If you re save the object it will update the image from vimeo.

You could use the same saving code for files as well as they require the same fields.

Here's what I ended up writing in the dataobject that has_one image eg. a page of with a thumbnail:

static $db = array(
      'VideoID' => 'HTMLText'
   );

static $has_one = array(
      'ThumbnailImage' => 'Image'
   );

function getCMSFields() {
      $fields = parent::getCMSFields();
      $fields->addFieldToTab('Root.Content.Main', new NumericField('VideoID', 'Vimeo Video Number'));
      return $fields;   
   }

function onBeforeWrite() {

      if(!empty($this->VideoID) && $this->VideoID!=0) {
      // call for large image (thumbnail_url)
         $ThumbnailCall = new RestfulService('http://vimeo.com/api/oembed.xml', 0);
         $params = array('url' => 'http://vimeo.com/'.$this->VideoID);
         $ThumbnailCall->setQueryString($params);
         $xmlResponse = $ThumbnailCall->request()->getBody();
         $thumbnailURL = $ThumbnailCall->getValue($xmlResponse, 'thumbnail_url');
         
         if(preg_match('/(.JPG|.jpg)$/',$thumbnailURL)) // check if thumbnail url is a jpg
         {
            $folderToSave = 'assets/Uploads/'; //if you want to save into another folder you will need to add one via the cms then change this path. Folders are a type of Folder DataObject.
            $folderObject = DataObject::get_one("Folder", "`Filename` = '{$folderToSave}'");
            if($folderObject)
            {
               //get image from url and save to folder
               $thumbnailToCopy = file_get_contents($thumbnailURL);
               $thumbnailExtraName = preg_replace('/.*?(_[0-9]{3,4})(.JPG|.jpg)$/','$1$2',$thumbnailURL); // renaming of the file, I strip off everything except the image width and the file extension.
               $thumbnailBaseName = str_replace('-', '_', $this->URLSegment); // takes the url segment as its base
               $thumbnailName = $thumbnailBaseName.'_thumbnail'.$thumbnailExtraName;
               
               $thumbnailFile = fopen('./../'.$folderToSave.$thumbnailName, 'w'); // opens existing or creates a new file
               fwrite($thumbnailFile, $thumbnailToCopy); //overwrites file
               fclose($thumbnailFile); //close file
               
               if(!DataObject::get_one('Image', "`Name` = '{$thumbnailName}'")) //checks if dataObject already exists, stops multiple records being created.
               {
                  $thumbnailObject = Object::create('Image');
                  $thumbnailObject->ParentID = $folderObject->ID; //assign folder of image as parent
                  $thumbnailObject->Name = $thumbnailName; //this function also sets the images Filename and title in a round about way. (see setName() in File.php)
                  $thumbnailObject->OwnerID = (Member::currentUser() ? Member::currentUser()->ID : 0); //assign current user as Owner
                  $thumbnailObject->write(); //write the object to the database
                  $this->ThumbnailImageID = DataObject::get_one('Image', "`Name` = '{$thumbnailName}'")->ID; //assign the object to the has_one, this took me ages to get. Basically it is the name of the has_one relationship with 'ID' tagged on the end and it must equal the new image objects ID.
               }
            }
         }
         
      }
      parent::onBeforeWrite();
   }

Avatar
purplespider

23 November 2011 at 12:53am Community Member, 81 Posts

Thank you so much for this, I've been trying to work out how to do exactly the same thing with Vimeo, and this works perfectly! Cheers!