2009-05-11 18:45:00 +01:00
< ? php
/*
2009-08-25 23:14:12 +01:00
* StatusNet - the distributed open - source microblogging tool
2009-08-25 23:12:20 +01:00
* Copyright ( C ) 2008 , 2009 , StatusNet , Inc .
2009-05-11 18:45:00 +01:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < http :// www . gnu . org / licenses />.
*/
2013-11-10 13:33:45 +00:00
if ( ! defined ( 'GNUSOCIAL' )) { exit ( 1 ); }
2009-05-11 18:45:00 +01:00
/**
* Table Definition for file
*/
2011-08-22 22:52:02 +01:00
class File extends Managed_DataObject
2009-05-11 18:45:00 +01:00
{
public $__table = 'file' ; // table name
2009-06-22 22:19:41 +01:00
public $id ; // int(4) primary_key not_null
2009-05-11 18:45:00 +01:00
public $url ; // varchar(255) unique_key
2009-06-22 23:48:31 +01:00
public $mimetype ; // varchar(50)
public $size ; // int(4)
public $title ; // varchar(255)
public $date ; // int(4)
public $protected ; // int(4)
public $filename ; // varchar(255)
2009-06-22 22:19:41 +01:00
public $modified ; // timestamp() not_null default_CURRENT_TIMESTAMP
2009-05-11 18:45:00 +01:00
2011-08-22 22:52:02 +01:00
public static function schemaDef ()
{
return array (
'fields' => array (
'id' => array ( 'type' => 'serial' , 'not null' => true ),
'url' => array ( 'type' => 'varchar' , 'length' => 255 , 'description' => 'destination URL after following redirections' ),
'mimetype' => array ( 'type' => 'varchar' , 'length' => 50 , 'description' => 'mime type of resource' ),
'size' => array ( 'type' => 'int' , 'description' => 'size of resource when available' ),
'title' => array ( 'type' => 'varchar' , 'length' => 255 , 'description' => 'title of resource when available' ),
'date' => array ( 'type' => 'int' , 'description' => 'date of resource according to http query' ),
'protected' => array ( 'type' => 'int' , 'description' => 'true when URL is private (needs login)' ),
'filename' => array ( 'type' => 'varchar' , 'length' => 255 , 'description' => 'if a local file, name of the file' ),
2014-04-21 19:39:28 +01:00
'width' => array ( 'type' => 'int' , 'description' => 'width in pixels, if it can be described as such and data is available' ),
'height' => array ( 'type' => 'int' , 'description' => 'height in pixels, if it can be described as such and data is available' ),
2011-08-22 22:52:02 +01:00
'modified' => array ( 'type' => 'timestamp' , 'not null' => true , 'description' => 'date this record was modified' ),
),
'primary key' => array ( 'id' ),
'unique keys' => array (
'file_url_key' => array ( 'url' ),
),
);
}
2009-05-13 19:27:32 +01:00
function isProtected ( $url ) {
return 'http://www.facebook.com/login.php' === $url ;
}
2010-03-10 21:39:42 +00:00
/**
* Save a new file record .
*
* @ param array $redir_data lookup data eg from File_redirection :: where ()
* @ param string $given_url
* @ return File
*/
2014-04-20 15:06:41 +01:00
public static function saveNew ( array $redir_data , $given_url ) {
2011-09-30 18:03:42 +01:00
// I don't know why we have to keep doing this but I'm adding this last check to avoid
// uniqueness bugs.
2013-08-18 12:04:58 +01:00
$x = File :: getKV ( 'url' , $given_url );
2011-09-30 18:03:42 +01:00
2013-11-10 13:33:45 +00:00
if ( ! $x instanceof File ) {
2011-09-30 18:03:42 +01:00
$x = new File ;
$x -> url = $given_url ;
if ( ! empty ( $redir_data [ 'protected' ])) $x -> protected = $redir_data [ 'protected' ];
if ( ! empty ( $redir_data [ 'title' ])) $x -> title = $redir_data [ 'title' ];
if ( ! empty ( $redir_data [ 'type' ])) $x -> mimetype = $redir_data [ 'type' ];
if ( ! empty ( $redir_data [ 'size' ])) $x -> size = intval ( $redir_data [ 'size' ]);
if ( isset ( $redir_data [ 'time' ]) && $redir_data [ 'time' ] > 0 ) $x -> date = intval ( $redir_data [ 'time' ]);
$file_id = $x -> insert ();
}
2009-05-13 19:27:32 +01:00
2010-03-10 22:31:29 +00:00
$x -> saveOembed ( $redir_data , $given_url );
return $x ;
}
/**
* Save embedding information for this file , if applicable .
*
* Normally this won ' t need to be called manually , as File :: saveNew ()
* takes care of it .
*
* @ param array $redir_data lookup data eg from File_redirection :: where ()
* @ param string $given_url
* @ return boolean success
*/
2013-08-29 09:27:39 +01:00
public function saveOembed ( array $redir_data , $given_url )
2010-03-10 22:31:29 +00:00
{
2009-05-13 19:27:32 +01:00
if ( isset ( $redir_data [ 'type' ])
2013-11-10 13:33:45 +00:00
&& (( 'text/html' === substr ( $redir_data [ 'type' ], 0 , 9 )
|| 'application/xhtml+xml' === substr ( $redir_data [ 'type' ], 0 , 21 )))) {
try {
$oembed_data = File_oembed :: _getOembed ( $given_url );
} catch ( Exception $e ) {
return false ;
}
2014-02-25 22:31:09 +00:00
if ( $oembed_data === false ) {
return false ;
}
2013-08-18 12:04:58 +01:00
$fo = File_oembed :: getKV ( 'file_id' , $this -> id );
2010-01-10 21:18:53 +00:00
2013-11-10 13:33:45 +00:00
if ( $fo instanceof File_oembed ) {
common_log ( LOG_WARNING , " Strangely, a File_oembed object exists for new file $file_id " , __FILE__ );
} else {
2010-03-10 22:31:29 +00:00
File_oembed :: saveNew ( $oembed_data , $this -> id );
return true ;
2010-01-10 21:18:53 +00:00
}
2009-05-13 19:27:32 +01:00
}
2010-03-10 22:31:29 +00:00
return false ;
2009-05-13 19:27:32 +01:00
}
2010-05-25 21:09:21 +01:00
/**
2010-11-15 19:00:42 +00:00
* Go look at a URL and possibly save data about it if it ' s new :
* - follow redirect chains and store them in file_redirection
* - look up oEmbed data and save it in file_oembed
* - if a thumbnail is available , save it in file_thumbnail
* - save file record with basic info
* - optionally save a file_to_post record
* - return the File object with the full reference
*
2010-05-25 21:09:21 +01:00
* @ fixme refactor this mess , it ' s gotten pretty scary .
2010-11-15 19:00:42 +00:00
* @ param string $given_url the URL we ' re looking at
* @ param int $notice_id ( optional )
* @ param bool $followRedirects defaults to true
*
* @ return mixed File on success , - 1 on some errors
*
* @ throws ServerException on some errors
2010-05-25 21:09:21 +01:00
*/
2010-11-15 19:00:42 +00:00
public function processNew ( $given_url , $notice_id = null , $followRedirects = true ) {
2009-05-13 19:27:32 +01:00
if ( empty ( $given_url )) return - 1 ; // error, no url to process
$given_url = File_redirection :: _canonUrl ( $given_url );
if ( empty ( $given_url )) return - 1 ; // error, no url to process
2013-08-18 12:04:58 +01:00
$file = File :: getKV ( 'url' , $given_url );
2009-06-25 19:10:34 +01:00
if ( empty ( $file )) {
2013-08-18 12:04:58 +01:00
$file_redir = File_redirection :: getKV ( 'url' , $given_url );
2009-06-25 19:10:34 +01:00
if ( empty ( $file_redir )) {
2010-05-25 21:09:21 +01:00
// @fixme for new URLs this also looks up non-redirect data
// such as target content type, size, etc, which we need
// for File::saveNew(); so we call it even if not following
// new redirects.
2009-05-13 19:27:32 +01:00
$redir_data = File_redirection :: where ( $given_url );
2009-09-27 21:52:15 +01:00
if ( is_array ( $redir_data )) {
$redir_url = $redir_data [ 'url' ];
} elseif ( is_string ( $redir_data )) {
$redir_url = $redir_data ;
2010-03-10 22:31:29 +00:00
$redir_data = array ();
2009-09-27 21:52:15 +01:00
} else {
2010-07-29 12:01:04 +01:00
// TRANS: Server exception thrown when a URL cannot be processed.
2010-07-30 18:25:55 +01:00
throw new ServerException ( sprintf ( _ ( " Cannot process URL '%s' " ), $given_url ));
2009-09-27 21:52:15 +01:00
}
2009-08-12 05:00:46 +01:00
// TODO: max field length
2010-05-25 21:09:21 +01:00
if ( $redir_url === $given_url || strlen ( $redir_url ) > 255 || ! $followRedirects ) {
2009-05-13 19:27:32 +01:00
$x = File :: saveNew ( $redir_data , $given_url );
$file_id = $x -> id ;
} else {
2010-05-25 21:09:21 +01:00
// This seems kind of messed up... for now skipping this part
// if we're already under a redirect, so we don't go into
// horrible infinite loops if we've been given an unstable
// redirect (where the final destination of the first request
// doesn't match what we get when we ask for it again).
//
// Seen in the wild with clojure.org, which redirects through
// wikispaces for auth and appends session data in the URL params.
$x = File :: processNew ( $redir_url , $notice_id , /*followRedirects*/ false );
2009-05-13 19:27:32 +01:00
$file_id = $x -> id ;
File_redirection :: saveNew ( $redir_data , $file_id , $given_url );
}
} else {
$file_id = $file_redir -> file_id ;
}
} else {
$file_id = $file -> id ;
$x = $file ;
}
if ( empty ( $x )) {
2013-08-18 12:04:58 +01:00
$x = File :: getKV ( 'id' , $file_id );
2009-07-30 21:55:09 +01:00
if ( empty ( $x )) {
2010-11-04 17:33:39 +00:00
// @todo FIXME: This could possibly be a clearer message :)
2010-07-29 12:01:04 +01:00
// TRANS: Server exception thrown when... Robin thinks something is impossible!
2010-11-04 17:33:39 +00:00
throw new ServerException ( _ ( 'Robin thinks something is impossible.' ));
2009-07-30 21:55:09 +01:00
}
2009-05-13 19:27:32 +01:00
}
2009-06-22 23:48:31 +01:00
2009-08-28 04:23:31 +01:00
if ( ! empty ( $notice_id )) {
File_to_post :: processNew ( $file_id , $notice_id );
}
2009-05-13 19:27:32 +01:00
return $x ;
}
2009-06-01 02:03:55 +01:00
2013-10-05 17:43:41 +01:00
public static function respectsQuota ( Profile $scoped , $fileSize ) {
2009-07-07 20:55:10 +01:00
if ( $fileSize > common_config ( 'attachments' , 'file_quota' )) {
2011-12-28 11:44:42 +00:00
// TRANS: Message used to be inserted as %2$s in the text "No file may
// TRANS: be larger than %1$d byte and the file you sent was %2$s.".
// TRANS: %1$d is the number of bytes of an uploaded file.
$fileSizeText = sprintf ( _m ( '%1$d byte' , '%1$d bytes' , $fileSize ), $fileSize );
$fileQuota = common_config ( 'attachments' , 'file_quota' );
2010-07-29 12:01:04 +01:00
// TRANS: Message given if an upload is larger than the configured maximum.
2011-12-28 11:44:42 +00:00
// TRANS: %1$d (used for plural) is the byte limit for uploads,
// TRANS: %2$s is the proper form of "n bytes". This is the only ways to have
// TRANS: gettext support multiple plurals in the same message, unfortunately...
2013-10-05 17:43:41 +01:00
throw new ClientException (
sprintf ( _m ( 'No file may be larger than %1$d byte and the file you sent was %2$s. Try to upload a smaller version.' ,
2011-12-28 11:44:42 +00:00
'No file may be larger than %1$d bytes and the file you sent was %2$s. Try to upload a smaller version.' ,
$fileQuota ),
2013-10-05 17:43:41 +01:00
$fileQuota , $fileSizeText ));
2009-06-01 02:03:55 +01:00
}
2013-10-05 17:43:41 +01:00
$file = new File ;
$query = " select sum(size) as total from file join file_to_post on file_to_post.file_id = file.id join notice on file_to_post.post_id = notice.id where profile_id = { $scoped -> id } and file.url like '%/notice/%/file' " ;
$file -> query ( $query );
$file -> fetch ();
$total = $file -> total + $fileSize ;
2009-06-01 02:03:55 +01:00
if ( $total > common_config ( 'attachments' , 'user_quota' )) {
2010-07-29 12:01:04 +01:00
// TRANS: Message given if an upload would exceed user quota.
2010-11-04 17:33:39 +00:00
// TRANS: %d (number) is the user quota in bytes and is used for plural.
2013-10-05 17:43:41 +01:00
throw new ClientException (
sprintf ( _m ( 'A file this large would exceed your user quota of %d byte.' ,
2010-11-04 17:33:39 +00:00
'A file this large would exceed your user quota of %d bytes.' ,
common_config ( 'attachments' , 'user_quota' )),
2013-10-05 17:43:41 +01:00
common_config ( 'attachments' , 'user_quota' )));
2009-06-01 02:03:55 +01:00
}
2009-07-22 06:05:44 +01:00
$query .= ' AND EXTRACT(month FROM file.modified) = EXTRACT(month FROM now()) and EXTRACT(year FROM file.modified) = EXTRACT(year FROM now())' ;
2013-10-05 17:43:41 +01:00
$file -> query ( $query );
$file -> fetch ();
$total = $file -> total + $fileSize ;
2009-06-01 02:03:55 +01:00
if ( $total > common_config ( 'attachments' , 'monthly_quota' )) {
2010-07-29 12:01:04 +01:00
// TRANS: Message given id an upload would exceed a user's monthly quota.
2010-11-04 17:33:39 +00:00
// TRANS: $d (number) is the monthly user quota in bytes and is used for plural.
2013-10-05 17:43:41 +01:00
throw new ClientException (
sprintf ( _m ( 'A file this large would exceed your monthly quota of %d byte.' ,
2010-11-04 17:33:39 +00:00
'A file this large would exceed your monthly quota of %d bytes.' ,
common_config ( 'attachments' , 'monthly_quota' )),
2013-10-05 17:43:41 +01:00
common_config ( 'attachments' , 'monthly_quota' )));
2009-06-01 02:03:55 +01:00
}
return true ;
}
2009-06-22 23:48:31 +01:00
// where should the file go?
2014-04-16 22:17:27 +01:00
static function filename ( Profile $profile , $origname , $mimetype )
2009-06-23 15:29:43 +01:00
{
2014-03-08 02:51:47 +00:00
try {
$ext = common_supported_mime_to_ext ( $mimetype );
} catch ( Exception $e ) {
// We don't support this mimetype, but let's guess the extension
$ext = substr ( strrchr ( $mimetype , '/' ), 1 );
2010-03-02 02:42:38 +00:00
}
2010-11-04 00:05:26 +00:00
2014-04-16 22:17:27 +01:00
// Normalize and make the original filename more URL friendly.
$origname = basename ( $origname );
if ( class_exists ( 'Normalizer' )) {
// http://php.net/manual/en/class.normalizer.php
// http://www.unicode.org/reports/tr15/
$origname = Normalizer :: normalize ( $origname , Normalizer :: FORM_KC );
}
$origname = preg_replace ( '/[^A-Za-z0-9\.\_]/' , '_' , $origname );
2009-06-23 15:29:43 +01:00
$nickname = $profile -> nickname ;
2014-04-16 22:17:27 +01:00
$datestamp = strftime ( '%Y%m%d' , time ());
do {
// generate new random strings until we don't run into a filename collision.
$random = strtolower ( common_confirmation_code ( 16 ));
$filename = " $nickname - $datestamp - $origname - $random . $ext " ;
} while ( file_exists ( self :: path ( $filename )));
return $filename ;
2009-06-23 15:29:43 +01:00
}
2009-06-22 23:48:31 +01:00
2010-02-01 16:48:31 +00:00
/**
* Validation for as - saved base filenames
*/
static function validFilename ( $filename )
{
2010-02-02 17:30:15 +00:00
return preg_match ( '/^[A-Za-z0-9._-]+$/' , $filename );
2010-02-01 16:48:31 +00:00
}
/**
* @ throws ClientException on invalid filename
*/
2009-06-23 15:29:43 +01:00
static function path ( $filename )
{
2010-02-01 16:48:31 +00:00
if ( ! self :: validFilename ( $filename )) {
2010-07-29 12:01:04 +01:00
// TRANS: Client exception thrown if a file upload does not have a valid name.
throw new ClientException ( _ ( " Invalid filename. " ));
2010-02-01 16:48:31 +00:00
}
2009-06-23 15:29:43 +01:00
$dir = common_config ( 'attachments' , 'dir' );
2009-06-22 23:48:31 +01:00
2009-06-23 15:29:43 +01:00
if ( $dir [ strlen ( $dir ) - 1 ] != '/' ) {
$dir .= '/' ;
}
2009-06-22 23:48:31 +01:00
2009-06-23 15:29:43 +01:00
return $dir . $filename ;
}
2009-06-22 23:48:31 +01:00
2009-06-23 15:29:43 +01:00
static function url ( $filename )
{
2010-02-01 16:48:31 +00:00
if ( ! self :: validFilename ( $filename )) {
2010-07-29 12:01:04 +01:00
// TRANS: Client exception thrown if a file upload does not have a valid name.
throw new ClientException ( _ ( " Invalid filename. " ));
2010-02-01 16:48:31 +00:00
}
2010-10-14 19:22:17 +01:00
if ( common_config ( 'site' , 'private' )) {
2009-06-22 23:48:31 +01:00
2010-01-05 22:47:37 +00:00
return common_local_url ( 'getfile' ,
array ( 'filename' => $filename ));
2009-06-22 23:48:31 +01:00
2010-10-14 19:22:17 +01:00
}
2009-06-22 23:48:31 +01:00
2010-10-14 19:22:17 +01:00
if ( StatusNet :: isHTTPS ()) {
$sslserver = common_config ( 'attachments' , 'sslserver' );
2009-06-22 23:48:31 +01:00
2010-10-14 19:22:17 +01:00
if ( empty ( $sslserver )) {
// XXX: this assumes that background dir == site dir + /file/
// not true if there's another server
if ( is_string ( common_config ( 'site' , 'sslserver' )) &&
mb_strlen ( common_config ( 'site' , 'sslserver' )) > 0 ) {
$server = common_config ( 'site' , 'sslserver' );
} else if ( common_config ( 'site' , 'server' )) {
$server = common_config ( 'site' , 'server' );
}
$path = common_config ( 'site' , 'path' ) . '/file/' ;
} else {
$server = $sslserver ;
$path = common_config ( 'attachments' , 'sslpath' );
if ( empty ( $path )) {
$path = common_config ( 'attachments' , 'path' );
}
2010-01-05 22:47:37 +00:00
}
2010-10-14 19:22:17 +01:00
$protocol = 'https' ;
} else {
$path = common_config ( 'attachments' , 'path' );
2010-01-05 22:47:37 +00:00
$server = common_config ( 'attachments' , 'server' );
2009-06-22 23:48:31 +01:00
2010-01-05 22:47:37 +00:00
if ( empty ( $server )) {
$server = common_config ( 'site' , 'server' );
}
2009-06-22 23:48:31 +01:00
2010-02-11 22:06:57 +00:00
$ssl = common_config ( 'attachments' , 'ssl' );
2010-01-05 22:47:37 +00:00
2010-02-11 22:06:57 +00:00
$protocol = ( $ssl ) ? 'https' : 'http' ;
2010-10-14 19:22:17 +01:00
}
2010-02-11 22:06:57 +00:00
2010-10-14 19:22:17 +01:00
if ( $path [ strlen ( $path ) - 1 ] != '/' ) {
$path .= '/' ;
2010-01-05 22:47:37 +00:00
}
2010-10-14 19:22:17 +01:00
if ( $path [ 0 ] != '/' ) {
$path = '/' . $path ;
}
return $protocol . '://' . $server . $path . $filename ;
2009-06-23 15:29:43 +01:00
}
2009-07-14 18:33:40 +01:00
2009-08-26 20:40:51 +01:00
function getEnclosure (){
$enclosure = ( object ) array ();
$enclosure -> title = $this -> title ;
$enclosure -> url = $this -> url ;
$enclosure -> title = $this -> title ;
$enclosure -> date = $this -> date ;
$enclosure -> modified = $this -> modified ;
$enclosure -> size = $this -> size ;
$enclosure -> mimetype = $this -> mimetype ;
2009-08-27 02:51:54 +01:00
if ( ! isset ( $this -> filename )){
2010-03-11 22:26:59 +00:00
$notEnclosureMimeTypes = array ( null , 'text/html' , 'application/xhtml+xml' );
2010-06-28 20:20:50 +01:00
$mimetype = $this -> mimetype ;
2010-03-24 23:30:27 +00:00
if ( $mimetype != null ){
$mimetype = strtolower ( $this -> mimetype );
}
2009-08-26 20:40:51 +01:00
$semicolon = strpos ( $mimetype , ';' );
if ( $semicolon ){
$mimetype = substr ( $mimetype , 0 , $semicolon );
}
if ( in_array ( $mimetype , $notEnclosureMimeTypes )){
2010-11-08 23:50:06 +00:00
// Never treat generic HTML links as an enclosure type!
// But if we have oEmbed info, we'll consider it golden.
2013-08-18 12:04:58 +01:00
$oembed = File_oembed :: getKV ( 'file_id' , $this -> id );
2010-11-08 23:50:06 +00:00
if ( $oembed && in_array ( $oembed -> type , array ( 'photo' , 'video' ))){
2009-08-27 02:51:54 +01:00
$mimetype = strtolower ( $oembed -> mimetype );
2009-08-26 20:40:51 +01:00
$semicolon = strpos ( $mimetype , ';' );
if ( $semicolon ){
$mimetype = substr ( $mimetype , 0 , $semicolon );
}
2010-11-09 20:04:07 +00:00
// @fixme uncertain if this is right.
// we want to expose things like YouTube videos as
// viewable attachments, but don't expose them as
// downloadable enclosures.....?
//if (in_array($mimetype, $notEnclosureMimeTypes)) {
// return false;
//} else {
2009-08-27 02:51:54 +01:00
if ( $oembed -> mimetype ) $enclosure -> mimetype = $oembed -> mimetype ;
if ( $oembed -> url ) $enclosure -> url = $oembed -> url ;
if ( $oembed -> title ) $enclosure -> title = $oembed -> title ;
if ( $oembed -> modified ) $enclosure -> modified = $oembed -> modified ;
unset ( $oembed -> size );
2010-11-09 20:04:07 +00:00
//}
2010-01-22 15:12:26 +00:00
} else {
return false ;
2009-08-26 20:40:51 +01:00
}
}
2009-07-14 18:33:40 +01:00
}
2009-08-27 02:51:54 +01:00
return $enclosure ;
2009-07-14 18:33:40 +01:00
}
2010-03-03 00:30:09 +00:00
// quick back-compat hack, since there's still code using this
function isEnclosure ()
{
$enclosure = $this -> getEnclosure ();
return ! empty ( $enclosure );
}
2010-11-09 01:22:01 +00:00
/**
* Get the attachment ' s thumbnail record , if any .
2014-04-21 19:39:28 +01:00
* Make sure you supply proper 'int' typed variables ( or null ) .
2010-11-09 01:22:01 +00:00
*
2014-04-21 19:39:28 +01:00
* @ param $width int Max width of thumbnail in pixels . ( if null , use common_config values )
* @ param $height int Max height of thumbnail in pixels . ( if null , square - crop to $width )
* @ param $crop bool Crop to the max - values ' aspect ratio
2014-04-21 10:35:42 +01:00
*
2010-11-09 01:22:01 +00:00
* @ return File_thumbnail
*/
2014-04-21 19:39:28 +01:00
public function getThumbnail ( $width = null , $height = null , $crop = false )
2010-11-09 01:22:01 +00:00
{
2014-04-21 19:39:28 +01:00
if ( $this -> width < 1 || $this -> height < 1 ) {
// Old files may have 0 until migrated with scripts/upgrade.php
return null ;
}
2014-04-21 10:35:42 +01:00
if ( $width === null ) {
2014-04-21 19:39:28 +01:00
$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
list ( $width , $height , $x , $y , $w2 , $h2 ) =
ImageFile :: getScalingValues ( $this -> width , $this -> height , $width , $height , $crop );
// Doublecheck that parameters are sane and integers.
if ( $width < 1 || $width > common_config ( 'thumbnail' , 'maxsize' )
|| $height < 1 || $height > common_config ( 'thumbnail' , 'maxsize' )) {
// Fail on bad width parameter.
throw new ServerException ( 'Bad thumbnail width or height parameter' );
2014-04-21 10:35:42 +01:00
}
$params = array ( 'file_id' => $this -> id ,
'width' => $width ,
2014-04-21 19:39:28 +01:00
'height' => $height );
2014-04-21 10:35:42 +01:00
$thumb = File_thumbnail :: pkeyGet ( $params );
if ( $thumb === null ) {
2014-04-21 19:39:28 +01:00
try {
$thumb = $this -> generateThumbnail ( $width , $height , $crop );
} catch ( UnsupportedMediaException $e ) {
// FIXME: Add "unknown media" icon or something
} catch ( ServerException $e ) {
// Probably a remote media file, maybe not available locally
}
2014-04-21 10:35:42 +01:00
}
return $thumb ;
2010-11-09 01:22:01 +00:00
}
2010-12-28 19:58:55 +00:00
2014-04-21 19:39:28 +01:00
/**
* Generate and store a thumbnail image for the uploaded file , if applicable .
* Call this only if you know what you ' re doing .
*
* @ param $width int Maximum thumbnail width in pixels
* @ param $height int Maximum thumbnail height in pixels , if null , crop to $width
*
* @ return File_thumbnail or null
*/
protected function generateThumbnail ( $width , $height , $crop )
{
$imgPath = null ;
$media = common_get_mime_media ( $this -> mimetype );
$width = intval ( $width );
if ( $height === null ) {
$height = $width ;
$crop = true ;
}
if ( Event :: handle ( 'CreateFileImageThumbnailSource' , array ( $this , & $imgPath , $media ))) {
switch ( $media ) {
case 'image' :
$imgPath = $this -> getPath ();
break ;
default :
throw new UnsupportedMediaException ( _ ( 'Unsupported media format.' ), $this -> getPath ());
}
}
if ( ! file_exists ( $imgPath )) {
throw new ServerException ( sprintf ( 'Thumbnail source is not stored locally: %s' , $imgPath ));
}
try {
$image = new ImageFile ( $this -> id , $imgPath );
} catch ( UnsupportedMediaException $e ) {
// Avoid deleting the original
if ( $image -> getPath () != $this -> getPath ()) {
$image -> unlink ();
}
throw $e ;
}
list ( $width , $height , $x , $y , $w2 , $h2 ) =
$image -> scaleToFit ( $width , $height , $crop );
$outname = " thumb- { $width } x { $height } - " . $this -> filename ;
$outpath = self :: path ( $outname );
$image -> resizeTo ( $outpath , $width , $height , $x , $y , $w2 , $h2 );
// Avoid deleting the original
if ( $image -> getPath () != $this -> getPath ()) {
$image -> unlink ();
}
return File_thumbnail :: saveThumbnail ( $this -> id ,
self :: url ( $outname ),
$width , $height );
}
2014-04-16 18:14:26 +01:00
public function getPath ()
{
return self :: path ( $this -> filename );
}
2014-04-16 22:17:27 +01:00
public function getUrl ()
{
return $this -> url ;
}
2014-04-16 18:14:26 +01:00
2010-12-28 20:57:31 +00:00
/**
* Blow the cache of notices that link to this URL
*
* @ param boolean $last Whether to blow the " last " cache too
*
* @ return void
*/
2010-12-28 19:58:55 +00:00
function blowCache ( $last = false )
{
self :: blow ( 'file:notice-ids:%s' , $this -> url );
if ( $last ) {
self :: blow ( 'file:notice-ids:%s;last' , $this -> url );
}
2010-12-28 21:44:49 +00:00
self :: blow ( 'file:notice-count:%d' , $this -> id );
2010-12-28 19:58:55 +00:00
}
/**
* Stream of notices linking to this URL
*
* @ param integer $offset Offset to show ; default is 0
* @ param integer $limit Limit of notices to show
* @ param integer $since_id Since this notice
* @ param integer $max_id Before this notice
*
* @ return array ids of notices that link to this file
*/
function stream ( $offset = 0 , $limit = NOTICES_PER_PAGE , $since_id = 0 , $max_id = 0 )
{
2011-03-24 22:04:19 +00:00
$stream = new FileNoticeStream ( $this );
2011-03-23 15:29:55 +00:00
return $stream -> getNotices ( $offset , $limit , $since_id , $max_id );
2010-12-28 19:58:55 +00:00
}
2010-12-28 21:44:49 +00:00
function noticeCount ()
{
$cacheKey = sprintf ( 'file:notice-count:%d' , $this -> id );
$count = self :: cacheGet ( $cacheKey );
if ( $count === false ) {
$f2p = new File_to_post ();
$f2p -> file_id = $this -> id ;
$count = $f2p -> count ();
self :: cacheSet ( $cacheKey , $count );
}
return $count ;
}
2009-05-11 18:45:00 +01:00
}