X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=classes%2FFile.php;h=8d0623bf489023ca0a08ee28d5a424fa5a02ddb2;hb=06d4cecf7f03adae35a50375cc4e91c9eda1fc9e;hp=ef9dbf14aba1226c744df6f55472350852bef1d7;hpb=749367e12f9742d7fd5ee028230fefa627599125;p=quix0rs-gnu-social.git diff --git a/classes/File.php b/classes/File.php index ef9dbf14ab..8d0623bf48 100644 --- a/classes/File.php +++ b/classes/File.php @@ -17,19 +17,12 @@ * along with this program. If not, see . */ -if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } - -require_once INSTALLDIR.'/classes/Memcached_DataObject.php'; -require_once INSTALLDIR.'/classes/File_redirection.php'; -require_once INSTALLDIR.'/classes/File_oembed.php'; -require_once INSTALLDIR.'/classes/File_thumbnail.php'; -require_once INSTALLDIR.'/classes/File_to_post.php'; -//require_once INSTALLDIR.'/classes/File_redirection.php'; +if (!defined('GNUSOCIAL')) { exit(1); } /** * Table Definition for file */ -class File extends Memcached_DataObject +class File extends Managed_DataObject { ###START_AUTOCODE /* the code below is auto generated do not remove the above tag */ @@ -45,25 +38,33 @@ class File extends Memcached_DataObject public $filename; // varchar(255) public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP - /* Static get */ - function staticGet($k,$v=NULL) { return Memcached_DataObject::staticGet('File',$k,$v); } - /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function isProtected($url) { - return 'http://www.facebook.com/login.php' === $url; + 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'), + + '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'), + ), + ); } - function getAttachments($post_id) { - $query = "select file.* from file join file_to_post on (file_id = file.id) join notice on (post_id = notice.id) where post_id = " . $this->escape($post_id); - $this->query($query); - $att = array(); - while ($this->fetch()) { - $att[] = clone($this); - } - $this->free(); - return $att; + function isProtected($url) { + return 'http://www.facebook.com/login.php' === $url; } /** @@ -74,14 +75,22 @@ class File extends Memcached_DataObject * @return File */ function saveNew(array $redir_data, $given_url) { - $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(); + + // I don't know why we have to keep doing this but I'm adding this last check to avoid + // uniqueness bugs. + + $x = File::getKV('url', $given_url); + + if (!$x instanceof File) { + $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(); + } $x->saveOembed($redir_data, $given_url); return $x; @@ -97,19 +106,26 @@ class File extends Memcached_DataObject * @param string $given_url * @return boolean success */ - public function saveOembed($redir_data, $given_url) + public function saveOembed(array $redir_data, $given_url) { if (isset($redir_data['type']) - && (('text/html' === substr($redir_data['type'], 0, 9) || 'application/xhtml+xml' === substr($redir_data['type'], 0, 21))) - && ($oembed_data = File_oembed::_getOembed($given_url))) { - - $fo = File_oembed::staticGet('file_id', $this->id); + && (('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; + } + if ($oembed_data === false) { + return false; + } + $fo = File_oembed::getKV('file_id', $this->id); - if (empty($fo)) { + if ($fo instanceof File_oembed) { + common_log(LOG_WARNING, "Strangely, a File_oembed object exists for new file $file_id", __FILE__); + } else { File_oembed::saveNew($oembed_data, $this->id); return true; - } else { - common_log(LOG_WARNING, "Strangely, a File_oembed object exists for new file $file_id", __FILE__); } } return false; @@ -137,9 +153,9 @@ class File extends Memcached_DataObject 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 - $file = File::staticGet('url', $given_url); + $file = File::getKV('url', $given_url); if (empty($file)) { - $file_redir = File_redirection::staticGet('url', $given_url); + $file_redir = File_redirection::getKV('url', $given_url); if (empty($file_redir)) { // @fixme for new URLs this also looks up non-redirect data // such as target content type, size, etc, which we need @@ -181,7 +197,7 @@ class File extends Memcached_DataObject } if (empty($x)) { - $x = File::staticGet($file_id); + $x = File::getKV('id', $file_id); if (empty($x)) { // @todo FIXME: This could possibly be a clearer message :) // TRANS: Server exception thrown when... Robin thinks something is impossible! @@ -195,41 +211,52 @@ class File extends Memcached_DataObject return $x; } - function isRespectsQuota($user,$fileSize) { - + public static function respectsQuota(Profile $scoped, $fileSize) { if ($fileSize > common_config('attachments', 'file_quota')) { + // 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'); // TRANS: Message given if an upload is larger than the configured maximum. - // TRANS: %1$d is the byte limit for uploads, %2$d is the byte count for the uploaded file. - // TRANS: %1$s is used for plural. - return sprintf(_m('No file may be larger than %1$d byte and the file you sent was %2$d bytes. Try to upload a smaller version.', - 'No file may be larger than %1$d bytes and the file you sent was %2$d bytes. Try to upload a smaller version.', - common_config('attachments', 'file_quota')), - common_config('attachments', 'file_quota'), $fileSize); + // 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... + 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.', + 'No file may be larger than %1$d bytes and the file you sent was %2$s. Try to upload a smaller version.', + $fileQuota), + $fileQuota, $fileSizeText)); } - $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 = {$user->id} and file.url like '%/notice/%/file'"; - $this->query($query); - $this->fetch(); - $total = $this->total + $fileSize; + $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; if ($total > common_config('attachments', 'user_quota')) { // TRANS: Message given if an upload would exceed user quota. // TRANS: %d (number) is the user quota in bytes and is used for plural. - return sprintf(_m('A file this large would exceed your user quota of %d byte.', + throw new ClientException( + sprintf(_m('A file this large would exceed your user quota of %d byte.', 'A file this large would exceed your user quota of %d bytes.', common_config('attachments', 'user_quota')), - common_config('attachments', 'user_quota')); + common_config('attachments', 'user_quota'))); } $query .= ' AND EXTRACT(month FROM file.modified) = EXTRACT(month FROM now()) and EXTRACT(year FROM file.modified) = EXTRACT(year FROM now())'; - $this->query($query); - $this->fetch(); - $total = $this->total + $fileSize; + $file->query($query); + $file->fetch(); + $total = $file->total + $fileSize; if ($total > common_config('attachments', 'monthly_quota')) { // TRANS: Message given id an upload would exceed a user's monthly quota. // TRANS: $d (number) is the monthly user quota in bytes and is used for plural. - return sprintf(_m('A file this large would exceed your monthly quota of %d byte.', + throw new ClientException( + sprintf(_m('A file this large would exceed your monthly quota of %d byte.', 'A file this large would exceed your monthly quota of %d bytes.', common_config('attachments', 'monthly_quota')), - common_config('attachments', 'monthly_quota')); + common_config('attachments', 'monthly_quota'))); } return true; } @@ -238,20 +265,13 @@ class File extends Memcached_DataObject static function filename($profile, $basename, $mimetype) { - require_once 'MIME/Type/Extension.php'; - - // We have to temporarily disable auto handling of PEAR errors... - PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); - - $mte = new MIME_Type_Extension(); - $ext = $mte->getExtension($mimetype); - if (PEAR::isError($ext)) { - $ext = strtolower(preg_replace('/\W/', '', $mimetype)); + 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); } - // Restore error handling. - PEAR::staticPopErrorHandling(); - $nickname = $profile->nickname; $datestamp = strftime('%Y%m%dT%H%M%S', time()); $random = strtolower(common_confirmation_code(32)); @@ -368,7 +388,7 @@ class File extends Memcached_DataObject if(in_array($mimetype,$notEnclosureMimeTypes)){ // Never treat generic HTML links as an enclosure type! // But if we have oEmbed info, we'll consider it golden. - $oembed = File_oembed::staticGet('file_id',$this->id); + $oembed = File_oembed::getKV('file_id',$this->id); if($oembed && in_array($oembed->type, array('photo', 'video'))){ $mimetype = strtolower($oembed->mimetype); $semicolon = strpos($mimetype,';'); @@ -410,6 +430,65 @@ class File extends Memcached_DataObject */ function getThumbnail() { - return File_thumbnail::staticGet('file_id', $this->id); + return File_thumbnail::getKV('file_id', $this->id); + } + + public function getPath() + { + return self::path($this->filename); + } + + /** + * Blow the cache of notices that link to this URL + * + * @param boolean $last Whether to blow the "last" cache too + * + * @return void + */ + + function blowCache($last=false) + { + self::blow('file:notice-ids:%s', $this->url); + if ($last) { + self::blow('file:notice-ids:%s;last', $this->url); + } + self::blow('file:notice-count:%d', $this->id); + } + + /** + * 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) + { + $stream = new FileNoticeStream($this); + return $stream->getNotices($offset, $limit, $since_id, $max_id); + } + + 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; } }