Merge branch 'dev' into 'dev'

Thumbnails storage in filesystem or database implementation

See merge request hubzilla/core!1588
This commit is contained in:
Mario 2019-04-13 21:19:06 +02:00
commit 9c8cb4dea3
6 changed files with 135 additions and 79 deletions

View File

@ -129,7 +129,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
if(file_exists($tmp_name)) { if(file_exists($tmp_name)) {
$base_image = $r[0]; $base_image = $r[0];
$gis = getimagesize($tmp_name); $gis = getimagesize($tmp_name);
logger('gis: ' . print_r($gis,true)); logger('gis: ' . print_r($gis,true), LOGGER_DEBUG);
$base_image['width'] = $gis[0]; $base_image['width'] = $gis[0];
$base_image['height'] = $gis[1]; $base_image['height'] = $gis[1];
$base_image['content'] = @file_get_contents($tmp_name); $base_image['content'] = @file_get_contents($tmp_name);
@ -190,24 +190,17 @@ logger('gis: ' . print_r($gis,true));
'filename' => $base_image['filename'], 'filename' => $base_image['filename'],
'album' => t('Cover Photos'), 'album' => t('Cover Photos'),
'os_path' => $base_image['os_path'], 'os_path' => $base_image['os_path'],
'display_path' => $base_image['display_path'] 'display_path' => $base_image['display_path'],
'photo_usage' => PHOTO_COVER
]; ];
$p['imgscale'] = 7; $r1 = $im->storeThumbnail($p, PHOTO_RES_COVER_1200);
$p['photo_usage'] = PHOTO_COVER;
$r1 = $im->save($p);
$im->doScaleImage(850,310); $im->doScaleImage(850,310);
$p['imgscale'] = 8; $r2 = $im->storeThumbnail($p, PHOTO_RES_COVER_850);
$r2 = $im->save($p);
$im->doScaleImage(425,160); $im->doScaleImage(425,160);
$p['imgscale'] = 9; $r3 = $im->storeThumbnail($p, PHOTO_RES_COVER_425);
$r3 = $im->save($p);
if($r1 === false || $r2 === false || $r3 === false) { if($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over. // if one failed, delete them all so we can start over.
@ -216,6 +209,17 @@ logger('gis: ' . print_r($gis,true));
dbesc($base_image['resource_id']), dbesc($base_image['resource_id']),
local_channel() local_channel()
); );
$x = q("SELECT content FROM photo WHERE resource_id = '%s' AND uid = %d AND os_storage = 1 AND imgscale >= 7",
dbesc($base_image['resource_id']),
local_channel()
);
if($x) {
foreach($x as $xx) {
@unlink(dbunescbin($xx['content']));
}
}
return; return;
} }

View File

@ -119,23 +119,20 @@ class Profile_photo extends \Zotlabs\Web\Controller {
'filename' => $base_image['filename'], 'filename' => $base_image['filename'],
'album' => t('Profile Photos'), 'album' => t('Profile Photos'),
'os_path' => $base_image['os_path'], 'os_path' => $base_image['os_path'],
'display_path' => $base_image['display_path'] 'display_path' => $base_image['display_path'],
'photo_usage' => PHOTO_PROFILE,
'edited' => dbescdate($base_image['edited'])
]; ];
$p['imgscale'] = PHOTO_RES_PROFILE_300;
$p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL); $p['photo_usage'] = (($is_default_profile) ? PHOTO_PROFILE : PHOTO_NORMAL);
$r1 = $im->save($p); $r1 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_300);
$im->scaleImage(80); $im->scaleImage(80);
$p['imgscale'] = PHOTO_RES_PROFILE_80; $r2 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_80);
$r2 = $im->save($p);
$im->scaleImage(48); $im->scaleImage(48);
$p['imgscale'] = PHOTO_RES_PROFILE_48; $r3 = $im->storeThumbnail($p, PHOTO_RES_PROFILE_48);
$r3 = $im->save($p);
if($r1 === false || $r2 === false || $r3 === false) { if($r1 === false || $r2 === false || $r3 === false) {
// if one failed, delete them all so we can start over. // if one failed, delete them all so we can start over.
@ -147,6 +144,20 @@ class Profile_photo extends \Zotlabs\Web\Controller {
intval(PHOTO_RES_PROFILE_80), intval(PHOTO_RES_PROFILE_80),
intval(PHOTO_RES_PROFILE_48) intval(PHOTO_RES_PROFILE_48)
); );
$x = q("SELECT content FROM photo WHERE resource_id = '%s' AND uid = %d AND os_storage = 1 AND imgscale IN ( %d, %d, %d )",
dbesc($base_image['resource_id']),
local_channel(),
intval(PHOTO_RES_PROFILE_300),
intval(PHOTO_RES_PROFILE_80),
intval(PHOTO_RES_PROFILE_48)
);
if($x) {
foreach($x as $xx) {
@unlink(dbunescbin($xx['content']));
}
}
return; return;
} }
@ -198,7 +209,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
$r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' $r = q("UPDATE xchan set xchan_photo_mimetype = '%s', xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s'
where xchan_hash = '%s'", where xchan_hash = '%s'",
dbesc($im->getType()), dbesc($im->getType()),
dbesc(datetime_convert()), dbescdate($base_image['edited']),
dbesc(z_root() . '/photo/profile/l/' . $channel['channel_id']), dbesc(z_root() . '/photo/profile/l/' . $channel['channel_id']),
dbesc(z_root() . '/photo/profile/m/' . $channel['channel_id']), dbesc(z_root() . '/photo/profile/m/' . $channel['channel_id']),
dbesc(z_root() . '/photo/profile/s/' . $channel['channel_id']), dbesc(z_root() . '/photo/profile/s/' . $channel['channel_id']),
@ -245,7 +256,7 @@ class Profile_photo extends \Zotlabs\Web\Controller {
else { else {
require_once('include/attach.php'); require_once('include/attach.php');
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash)); $res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash, 'nosync' => true));
logger('attach_store: ' . print_r($res,true)); logger('attach_store: ' . print_r($res,true));
} }
@ -353,20 +364,23 @@ class Profile_photo extends \Zotlabs\Web\Controller {
if($havescale) { if($havescale) {
// unset any existing profile photos // unset any existing profile photos
$r = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d", $x = q("UPDATE photo SET photo_usage = %d WHERE photo_usage = %d AND uid = %d",
intval(PHOTO_NORMAL), intval(PHOTO_NORMAL),
intval(PHOTO_PROFILE), intval(PHOTO_PROFILE),
intval(local_channel())); intval(local_channel())
);
$r = q("UPDATE photo SET photo_usage = %d WHERE uid = %d AND resource_id = '%s'", $edited = datetime_convert();
$x = q("UPDATE photo SET photo_usage = %d, edited = '%s' WHERE uid = %d AND resource_id = '%s' AND imgscale > 0",
intval(PHOTO_PROFILE), intval(PHOTO_PROFILE),
dbescdate($edited),
intval(local_channel()), intval(local_channel()),
dbesc($resource_id) dbesc($resource_id)
); );
$r = q("UPDATE xchan set xchan_photo_date = '%s' $x = q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'",
where xchan_hash = '%s'", dbescdate($edited),
dbesc(datetime_convert()),
dbesc($channel['xchan_hash']) dbesc($channel['xchan_hash'])
); );

View File

@ -448,6 +448,7 @@ abstract class PhotoDriver {
$p['width'] = (($arr['width']) ? $arr['width'] : $this->getWidth()); $p['width'] = (($arr['width']) ? $arr['width'] : $this->getWidth());
$p['height'] = (($arr['height']) ? $arr['height'] : $this->getHeight()); $p['height'] = (($arr['height']) ? $arr['height'] : $this->getHeight());
$p['expires'] = (($arr['expires']) ? $arr['expires'] : gmdate('Y-m-d H:i:s', time() + get_config('system', 'photo_cache_time', 86400))); $p['expires'] = (($arr['expires']) ? $arr['expires'] : gmdate('Y-m-d H:i:s', time() + get_config('system', 'photo_cache_time', 86400)));
$p['profile'] = ((array_key_exists('profile', $arr)) ? intval($arr['profile']) : 0);
if(! intval($p['imgscale'])) if(! intval($p['imgscale']))
logger('save: ' . print_r($arr, true), LOGGER_DATA); logger('save: ' . print_r($arr, true), LOGGER_DATA);
@ -481,14 +482,15 @@ abstract class PhotoDriver {
allow_gid = '%s', allow_gid = '%s',
deny_cid = '%s', deny_cid = '%s',
deny_gid = '%s', deny_gid = '%s',
expires = '%s' expires = '%s',
profile = %d
where id = %d", where id = %d",
intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires']), intval($x[0]['id'])); intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires']), intval($p['profile']), intval($x[0]['id']));
} else { } else {
$p['created'] = (($arr['created']) ? $arr['created'] : $p['edited']); $p['created'] = (($arr['created']) ? $arr['created'] : $p['edited']);
$r = q("INSERT INTO photo $r = q("INSERT INTO photo
( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid, expires ) ( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid, expires, profile )
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )", intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires'])); VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d)", intval($p['aid']), intval($p['uid']), dbesc($p['xchan']), dbesc($p['resource_id']), dbescdate($p['created']), dbescdate($p['edited']), dbesc(basename($p['filename'])), dbesc($p['mimetype']), dbesc($p['album']), intval($p['height']), intval($p['width']), (intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())), intval($p['os_storage']), (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())), intval($p['imgscale']), intval($p['photo_usage']), dbesc($p['title']), dbesc($p['description']), dbesc($p['os_path']), dbesc($p['display_path']), dbesc($p['allow_cid']), dbesc($p['allow_gid']), dbesc($p['deny_cid']), dbesc($p['deny_gid']), dbescdate($p['expires']), intval($p['profile']));
} }
logger('Photo save imgscale ' . $p['imgscale'] . ' returned ' . intval($r)); logger('Photo save imgscale ' . $p['imgscale'] . ' returned ' . intval($r));

View File

@ -1345,6 +1345,7 @@ function sync_files($channel, $files) {
logger('attachment store failed',LOGGER_NORMAL,LOG_ERR); logger('attachment store failed',LOGGER_NORMAL,LOG_ERR);
} }
if($f['photo']) { if($f['photo']) {
foreach($f['photo'] as $p) { foreach($f['photo'] as $p) {
unset($p['id']); unset($p['id']);
$p['aid'] = $channel['channel_account_id']; $p['aid'] = $channel['channel_account_id'];
@ -1366,6 +1367,7 @@ function sync_files($channel, $files) {
dbesc($p['resource_id']), dbesc($p['resource_id']),
intval($channel['channel_id']) intval($channel['channel_id'])
); );
$update_xchan = $p['edited'];
} }
// same for cover photos // same for cover photos
@ -1385,7 +1387,7 @@ function sync_files($channel, $files) {
else else
$p['content'] = (($p['content'])? base64_decode($p['content']) : ''); $p['content'] = (($p['content'])? base64_decode($p['content']) : '');
if(intval($p['imgscale']) && intval($p['os_storage']) && (! empty($p['content']))) { if(intval($p['imgscale']) && (! empty($p['content']))) {
$time = datetime_convert(); $time = datetime_convert();
@ -1395,10 +1397,10 @@ function sync_files($channel, $files) {
'resource' => $p['resource_id'], 'resource' => $p['resource_id'],
'revision' => 0, 'revision' => 0,
'signature' => base64url_encode(rsa_sign($channel['channel_hash'] . '.' . $time, $channel['channel_prvkey'])), 'signature' => base64url_encode(rsa_sign($channel['channel_hash'] . '.' . $time, $channel['channel_prvkey'])),
'resolution' => $p['imgscale'] 'resolution' => intval($p['imgscale'])
); );
$stored_image = $newfname . '-' . intval($p['imgscale']); $stored_image = $newfname . '-' . $p['imgscale'];
$fp = fopen($stored_image,'w'); $fp = fopen($stored_image,'w');
if(! $fp) { if(! $fp) {
@ -1407,7 +1409,6 @@ function sync_files($channel, $files) {
} }
$redirects = 0; $redirects = 0;
$headers = []; $headers = [];
$headers['Accept'] = 'application/x-zot+json' ; $headers['Accept'] = 'application/x-zot+json' ;
$headers['Sigtoken'] = random_string(); $headers['Sigtoken'] = random_string();
@ -1415,6 +1416,18 @@ function sync_files($channel, $files) {
$x = z_post_url($fetch_url,$parr,$redirects,[ 'filep' => $fp, 'headers' => $headers]); $x = z_post_url($fetch_url,$parr,$redirects,[ 'filep' => $fp, 'headers' => $headers]);
fclose($fp); fclose($fp);
// Override remote hub thumbnails storage settings
if(! boolval(get_config('system','filesystem_storage_thumbnails', 0))) {
$p['os_storage'] = 0;
$p['content'] = file_get_contents($stored_image);
@unlink($stored_image);
}
else {
$p['os_storage'] = 1;
$p['content'] = $stored_image;
$p['os_syspath'] = $stored_image;
}
} }
if(!isset($p['display_path'])) if(!isset($p['display_path']))
@ -1446,6 +1459,16 @@ function sync_files($channel, $files) {
create_table_from_array('photo',$p, [ 'content' ] ); create_table_from_array('photo',$p, [ 'content' ] );
} }
} }
}
// Set xchan photo date to prevent thumbnails fetch for clones on profile update packet recieve
if(isset($update_xchan)) {
$x = q("UPDATE xchan SET xchan_photo_date = '%s' WHERE xchan_hash = '%s'",
dbescdate($update_xchan),
dbesc($channel['channel_hash'])
);
} }
\Zotlabs\Daemon\Master::Summon([ 'Thumbnail' , $att['hash'] ]); \Zotlabs\Daemon\Master::Summon([ 'Thumbnail' , $att['hash'] ]);

View File

@ -277,8 +277,7 @@ function photo_upload($channel, $observer, $args) {
if(($width > 1024 || $height > 1024) && (! $errors)) if(($width > 1024 || $height > 1024) && (! $errors))
$ph->scaleImage(1024); $ph->scaleImage(1024);
$p['imgscale'] = 1; $r1 = $ph->storeThumbnail($p, PHOTO_RES_1024);
$r1 = $ph->save($p);
$link[1] = array( $link[1] = array(
'rel' => 'alternate', 'rel' => 'alternate',
'type' => 'text/html', 'type' => 'text/html',
@ -292,8 +291,7 @@ function photo_upload($channel, $observer, $args) {
if(($width > 640 || $height > 640) && (! $errors)) if(($width > 640 || $height > 640) && (! $errors))
$ph->scaleImage(640); $ph->scaleImage(640);
$p['imgscale'] = 2; $r2 = $ph->storeThumbnail($p, PHOTO_RES_640);
$r2 = $ph->save($p);
$link[2] = array( $link[2] = array(
'rel' => 'alternate', 'rel' => 'alternate',
'type' => 'text/html', 'type' => 'text/html',
@ -307,8 +305,7 @@ function photo_upload($channel, $observer, $args) {
if(($width > 320 || $height > 320) && (! $errors)) if(($width > 320 || $height > 320) && (! $errors))
$ph->scaleImage(320); $ph->scaleImage(320);
$p['imgscale'] = 3; $r3 = $ph->storeThumbnail($p, PHOTO_RES_320);
$r3 = $ph->save($p);
$link[3] = array( $link[3] = array(
'rel' => 'alternate', 'rel' => 'alternate',
'type' => 'text/html', 'type' => 'text/html',

View File

@ -925,11 +925,27 @@ function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
$local = q("select channel_account_id, channel_id from channel where channel_hash = '%s' limit 1", $local = q("select channel_account_id, channel_id from channel where channel_hash = '%s' limit 1",
dbesc($xchan_hash) dbesc($xchan_hash)
); );
if($local) { if($local) {
// @FIXME This should be removed in future when profile photo update by file sync procedure will be applied
// on most hubs in the network
// <---
$ph = z_fetch_url($arr['photo'], true); $ph = z_fetch_url($arr['photo'], true);
if($ph['success']) { if($ph['success']) {
// Do not fetch already received thumbnails
$x = q("SELECT resource_id FROM photo WHERE uid = %d AND imgscale = %d AND filesize = %d LIMIT 1",
intval($local[0]['channel_id']),
intval(PHOTO_RES_PROFILE_300),
strlen($ph['body'])
);
if($x)
$hash = $x[0]['resource_id'];
else
$hash = import_channel_photo($ph['body'], $arr['photo_mimetype'], $local[0]['channel_account_id'], $local[0]['channel_id']); $hash = import_channel_photo($ph['body'], $arr['photo_mimetype'], $local[0]['channel_account_id'], $local[0]['channel_id']);
}
if($hash) { if($hash) {
// unless proven otherwise // unless proven otherwise
@ -955,6 +971,7 @@ function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
); );
} }
} }
// --->
// reset the names in case they got messed up when we had a bug in this function // reset the names in case they got messed up when we had a bug in this function
$photos = array( $photos = array(
@ -965,7 +982,6 @@ function import_xchan($arr, $ud_flags = UPDATE_FLAGS_UPDATED, $ud_arr = null) {
false false
); );
} }
}
else { else {
$photos = import_xchan_photo($arr['photo'], $xchan_hash); $photos = import_xchan_photo($arr['photo'], $xchan_hash);
} }