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.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Data Model Questions /

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

Saving image from URL without CMS field


Go to End


4 Posts   8176 Views

Avatar
J

Community Member, 3 Posts

8 June 2010 at 12:07pm

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

Community Member, 9 Posts

11 June 2010 at 8:57am

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

Community Member, 3 Posts

12 June 2010 at 2:32am

Edited: 12/06/2010 2:34am

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

Community Member, 89 Posts

23 November 2011 at 12:53am

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!