+ // Get some more information about this file through our ImageFile class
+ $image = ImageFile::fromFileObject($this);
+ if ($image->animated && !common_config('thumbnail', 'animated')) {
+ // null means "always use file as thumbnail"
+ // false means you get choice between frozen frame or original when calling getThumbnail
+ if (is_null(common_config('thumbnail', 'animated')) || !$force_still) {
+ throw new UseFileAsThumbnailException($this->id);
+ }
+ }
+
+ if ($width === null) {
+ $width = common_config('thumbnail', 'width');
+ $height = common_config('thumbnail', 'height');
+ $crop = common_config('thumbnail', 'crop');
+ }
+
+ if ($height === null) {
+ $height = $width;
+ $crop = true;
+ }
+
+ // Get proper aspect ratio width and height before lookup
+ // We have to do it through an ImageFile object because of orientation etc.
+ // Only other solution would've been to rotate + rewrite uploaded files.
+ list($width, $height, $x, $y, $w, $h) =
+ $image->scaleToFit($width, $height, $crop);
+
+ $params = array('file_id'=> $this->id,
+ 'width' => $width,
+ 'height' => $height);
+ $thumb = File_thumbnail::pkeyGet($params);
+ if ($thumb instanceof File_thumbnail) {
+ return $thumb;
+ }
+
+ // throws exception on failure to generate thumbnail
+ $outname = "thumb-{$width}x{$height}-" . $image->filename;
+ $outpath = self::path($outname);
+
+ // The boundary box for our resizing
+ $box = array('width'=>$width, 'height'=>$height,
+ 'x'=>$x, 'y'=>$y,
+ 'w'=>$w, 'h'=>$h);
+
+ // Doublecheck that parameters are sane and integers.
+ if ($box['width'] < 1 || $box['width'] > common_config('thumbnail', 'maxsize')
+ || $box['height'] < 1 || $box['height'] > common_config('thumbnail', 'maxsize')
+ || $box['w'] < 1 || $box['x'] >= $image->width
+ || $box['h'] < 1 || $box['y'] >= $image->height) {
+ // Fail on bad width parameter. If this occurs, it's due to algorithm in ImageFile->scaleToFit
+ common_debug("Boundary box parameters for resize of {$image->filepath} : ".var_export($box,true));
+ throw new ServerException('Bad thumbnail size parameters.');
+ }
+
+ common_debug(sprintf('Generating a thumbnail of File id==%u of size %ux%u', $this->id, $width, $height));
+ // Perform resize and store into file
+ $image->resizeTo($outpath, $box);
+
+ // Avoid deleting the original
+ if ($image->getPath() != self::path($image->filename)) {
+ $image->unlink();
+ }
+ return File_thumbnail::saveThumbnail($this->id,
+ self::url($outname),
+ $width, $height,
+ $outname);
+ }
+
+ public function getPath()
+ {
+ return self::path($this->filename);
+ }
+
+ public function getUrl()
+ {
+ if (!empty($this->filename)) {
+ // A locally stored file, so let's generate a URL for our instance.
+ $url = self::url($this->filename);
+ if (self::hashurl($url) !== $this->urlhash) {
+ // For indexing purposes, in case we do a lookup on the 'url' field.
+ // also we're fixing possible changes from http to https, or paths
+ $this->updateUrl($url);
+ }
+ return $url;
+ }
+
+ // No local filename available, return the URL we have stored
+ return $this->url;
+ }
+
+ static public function getByUrl($url)
+ {
+ $file = new File();
+ $file->urlhash = self::hashurl($url);
+ if (!$file->find(true)) {
+ throw new NoResultException($file);
+ }
+ return $file;
+ }
+
+ public function updateUrl($url)
+ {
+ $file = File::getKV('urlhash', self::hashurl($url));
+ if ($file instanceof File) {
+ throw new ServerException('URL already exists in DB');
+ }
+ $sql = 'UPDATE %1$s SET urlhash=%2$s, url=%3$s WHERE urlhash=%4$s;';
+ $result = $this->query(sprintf($sql, $this->__table,
+ $this->_quote((string)self::hashurl($url)),
+ $this->_quote((string)$url),
+ $this->_quote((string)$this->urlhash)));
+ if ($result === false) {
+ common_log_db_error($this, 'UPDATE', __FILE__);
+ throw new ServerException("Could not UPDATE {$this->__table}.url");
+ }
+
+ return $result;