mirror of
https://github.com/Piwigo/Piwigo.git
synced 2025-04-26 11:19:55 +03:00
fixes #1419 add photos in a lounge as a temporary space
* at the end of the upload of after a maximum duration, move the photos from the lounge to their actual categories. * do not invalidate user cache when photos are added in the lounge, thus avoiding to rebuild cache on every photo uploaded * the lounge system activates itself only beyond 50k (by default) photo
This commit is contained in:
parent
4aa7a7b9bf
commit
ac0d1a5b47
13 changed files with 307 additions and 7 deletions
|
@ -1888,6 +1888,129 @@ function compare_image_tag_lists($taglist_before, $taglist_after)
|
|||
return $images_to_update;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instead of associating images to categories, add them in the lounge, waiting for take-off.
|
||||
*
|
||||
* @since 12
|
||||
* @param array $images - list of image ids
|
||||
* @param array $categories - list of category ids
|
||||
*/
|
||||
function fill_lounge($images, $categories)
|
||||
{
|
||||
$inserts = array();
|
||||
foreach ($categories as $category_id)
|
||||
{
|
||||
foreach ($images as $image_id)
|
||||
{
|
||||
$inserts[] = array(
|
||||
'image_id' => $image_id,
|
||||
'category_id' => $category_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($inserts))
|
||||
{
|
||||
mass_inserts(
|
||||
LOUNGE_TABLE,
|
||||
array_keys($inserts[0]),
|
||||
$inserts
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Move images from the lounge to the categories they were intended for.
|
||||
*
|
||||
* @since 12
|
||||
* @param boolean $invalidate_user_cache
|
||||
* @return int number of images moved
|
||||
*/
|
||||
function empty_lounge($invalidate_user_cache=true)
|
||||
{
|
||||
global $logger;
|
||||
|
||||
if (isset($conf['empty_lounge_running']))
|
||||
{
|
||||
list($running_exec_id, $running_exec_start_time) = explode('-', $conf['empty_lounge_running']);
|
||||
if (time() - $running_exec_start_time > 60)
|
||||
{
|
||||
$logger->debug(__FUNCTION__.', exec='.$running_exec_id.', timeout stopped by another call to the function');
|
||||
conf_delete_param('empty_lounge_running');
|
||||
}
|
||||
}
|
||||
|
||||
$exec_id = generate_key(4);
|
||||
$logger->debug(__FUNCTION__.', exec='.$exec_id.', begins');
|
||||
|
||||
// if lounge is already being emptied, skip
|
||||
$query = '
|
||||
INSERT IGNORE
|
||||
INTO '.CONFIG_TABLE.'
|
||||
SET param="empty_lounge_running"
|
||||
, value="'.$exec_id.'-'.time().'"
|
||||
;';
|
||||
pwg_query($query);
|
||||
|
||||
list($empty_lounge_running) = pwg_db_fetch_row(pwg_query('SELECT value FROM '.CONFIG_TABLE.' WHERE param = "empty_lounge_running"'));
|
||||
list($running_exec_id,) = explode('-', $empty_lounge_running);
|
||||
|
||||
if ($running_exec_id != $exec_id)
|
||||
{
|
||||
$logger->debug(__FUNCTION__.', exec='.$exec_id.', skip');
|
||||
return;
|
||||
}
|
||||
$logger->debug(__FUNCTION__.', exec='.$exec_id.' wins the race and gets the token!');
|
||||
sleep(5);
|
||||
|
||||
$max_image_id = 0;
|
||||
|
||||
$query = '
|
||||
SELECT
|
||||
image_id,
|
||||
category_id
|
||||
FROM '.LOUNGE_TABLE.'
|
||||
ORDER BY category_id ASC, image_id ASC
|
||||
;';
|
||||
|
||||
$rows = query2array($query);
|
||||
|
||||
$images = array();
|
||||
foreach ($rows as $idx => $row)
|
||||
{
|
||||
if ($row['image_id'] > $max_image_id)
|
||||
{
|
||||
$max_image_id = $row['image_id'];
|
||||
}
|
||||
|
||||
$images[] = $row['image_id'];
|
||||
|
||||
if (!isset($rows[$idx+1]) or $rows[$idx+1]['category_id'] != $row['category_id'])
|
||||
{
|
||||
// if we're at the end of the loop OR if category changes
|
||||
associate_images_to_categories($images, array($row['category_id']));
|
||||
$images = array();
|
||||
}
|
||||
}
|
||||
|
||||
$query = '
|
||||
DELETE
|
||||
FROM '.LOUNGE_TABLE.'
|
||||
WHERE image_id <= '.$max_image_id.'
|
||||
;';
|
||||
pwg_query($query);
|
||||
|
||||
if ($invalidate_user_cache)
|
||||
{
|
||||
invalidate_user_cache();
|
||||
}
|
||||
|
||||
conf_delete_param('empty_lounge_running');
|
||||
|
||||
$logger->debug(__FUNCTION__.', exec='.$exec_id.', ends');
|
||||
return count($rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associate a list of images to a list of categories.
|
||||
* The function will not duplicate links and will preserve ranks.
|
||||
|
@ -3140,12 +3263,28 @@ SELECT path
|
|||
*/
|
||||
function get_orphans()
|
||||
{
|
||||
// exclude images in the lounge
|
||||
$query = '
|
||||
SELECT
|
||||
image_id
|
||||
FROM '.LOUNGE_TABLE.'
|
||||
;';
|
||||
$lounged_ids = query2array($query, null, 'image_id');
|
||||
|
||||
$query = '
|
||||
SELECT
|
||||
id
|
||||
FROM '.IMAGES_TABLE.'
|
||||
LEFT JOIN '.IMAGE_CATEGORY_TABLE.' ON id = image_id
|
||||
WHERE category_id is null
|
||||
WHERE category_id is null';
|
||||
|
||||
if (count($lounged_ids) > 0)
|
||||
{
|
||||
$query .= '
|
||||
AND id NOT IN ('.implode(',', $lounged_ids).')';
|
||||
}
|
||||
|
||||
$query.= '
|
||||
ORDER BY id ASC
|
||||
;';
|
||||
|
||||
|
|
|
@ -362,12 +362,31 @@ SELECT
|
|||
pwg_activity('photo', $image_id, 'add');
|
||||
}
|
||||
|
||||
if (!isset($conf['lounge_active']))
|
||||
{
|
||||
conf_update_param('lounge_active', false, true);
|
||||
}
|
||||
|
||||
if (!$conf['lounge_active'])
|
||||
{
|
||||
// check if we need to use the lounge from now
|
||||
list($nb_photos) = pwg_db_fetch_row(pwg_query('SELECT COUNT(*) FROM '.IMAGES_TABLE.';'));
|
||||
if ($nb_photos >= $conf['lounge_activate_threshold'])
|
||||
{
|
||||
conf_update_param('lounge_active', true, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($categories) and count($categories) > 0)
|
||||
{
|
||||
associate_images_to_categories(
|
||||
array($image_id),
|
||||
$categories
|
||||
);
|
||||
if ($conf['lounge_active'])
|
||||
{
|
||||
fill_lounge(array($image_id), $categories);
|
||||
}
|
||||
else
|
||||
{
|
||||
associate_images_to_categories(array($image_id), $categories);
|
||||
}
|
||||
}
|
||||
|
||||
// update metadata from the uploaded file (exif/iptc)
|
||||
|
@ -377,7 +396,10 @@ SELECT
|
|||
}
|
||||
sync_metadata(array($image_id));
|
||||
|
||||
invalidate_user_cache();
|
||||
if (!$conf['lounge_active'])
|
||||
{
|
||||
invalidate_user_cache();
|
||||
}
|
||||
|
||||
// cache a derivative
|
||||
$query = '
|
||||
|
|
|
@ -77,6 +77,7 @@ switch ($action)
|
|||
}
|
||||
case 'user_cache' :
|
||||
{
|
||||
empty_lounge(false);
|
||||
invalidate_user_cache();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -222,6 +222,14 @@ jQuery(document).ready(function(){
|
|||
|
||||
Piecon.reset();
|
||||
|
||||
jQuery.ajax({
|
||||
url: "ws.php?format=json&method=pwg.images.emptyLounge",
|
||||
type:"POST",
|
||||
data: {
|
||||
pwg_token: pwg_token
|
||||
}
|
||||
});
|
||||
|
||||
jQuery(".selectAlbum, .selectFiles, #permissions, .showFieldset").hide();
|
||||
|
||||
jQuery(".infos").append('<ul><li>'+sprintf(photosUploaded_label, uploadedPhotos.length)+'</li></ul>');
|
||||
|
|
|
@ -151,6 +151,8 @@ if (isset($conf['order_by_inside_category_custom']))
|
|||
$conf['order_by_inside_category'] = $conf['order_by_inside_category_custom'];
|
||||
}
|
||||
|
||||
check_lounge();
|
||||
|
||||
include(PHPWG_ROOT_PATH.'include/user.inc.php');
|
||||
|
||||
if (in_array( substr($user['language'],0,2), array('fr','it','de','es','pl','ru','nl','tr','da') ) )
|
||||
|
|
|
@ -433,6 +433,17 @@ $conf['session_gc_probability'] = 1;
|
|||
// | debug/performance |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
// number of photos beyond which individual photos are added in the
|
||||
// lounge, a temporary zone where photos wait before being "launched".
|
||||
// 50k photos by default.
|
||||
$conf['lounge_activate_threshold'] = 50000;
|
||||
|
||||
// Lounge is automatically emptied (photos are being pushed to their
|
||||
// albums) when the oldest one reaches this duration. Lounge can be emptied
|
||||
// before, either manually or at the end of the upload. In seconds.
|
||||
// 5 minutes by default.
|
||||
$conf['lounge_max_duration'] = 5*60;
|
||||
|
||||
// show_queries : for debug purpose, show queries and execution times
|
||||
$conf['show_queries'] = false;
|
||||
|
||||
|
|
|
@ -100,5 +100,7 @@ if (!defined('IMAGE_FORMAT_TABLE'))
|
|||
define('IMAGE_FORMAT_TABLE', $prefixeTable.'image_format');
|
||||
if (!defined('ACTIVITY_TABLE'))
|
||||
define('ACTIVITY_TABLE', $prefixeTable.'activity');
|
||||
if (!defined('LOUNGE_TABLE'))
|
||||
define('LOUNGE_TABLE', $prefixeTable.'lounge');
|
||||
|
||||
?>
|
||||
|
|
|
@ -2266,4 +2266,48 @@ function safe_version_compare($a, $b, $op=null)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the lounge needs to be emptied automatically.
|
||||
*
|
||||
* @since 12
|
||||
*/
|
||||
function check_lounge()
|
||||
{
|
||||
global $conf;
|
||||
|
||||
if (!isset($conf['lounge_active']) or !$conf['lounge_active'])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($_REQUEST['method']) and in_array($_REQUEST['method'], array('pwg.images.upload', 'pwg.images.uploadAsync')))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// is the oldest photo in the lounge older than lounge maximum waiting time?
|
||||
$query = '
|
||||
SELECT
|
||||
image_id,
|
||||
date_available,
|
||||
NOW() AS dbnow
|
||||
FROM '.LOUNGE_TABLE.'
|
||||
JOIN '.IMAGES_TABLE.' ON image_id = id
|
||||
ORDER BY image_id ASC
|
||||
LIMIT 1
|
||||
;';
|
||||
$voyagers = query2array($query);
|
||||
if (count($voyagers))
|
||||
{
|
||||
$voyager = $voyagers[0];
|
||||
$age = strtotime($voyager['dbnow']) - strtotime($voyager['date_available']);
|
||||
|
||||
if ($age > $conf['lounge_max_duration'])
|
||||
{
|
||||
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
|
||||
empty_lounge();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -475,6 +475,11 @@ SELECT image_id
|
|||
*/
|
||||
function get_computed_categories(&$userdata, $filter_days=null)
|
||||
{
|
||||
global $logger;
|
||||
|
||||
$start_time = get_moment();
|
||||
$logger->debug(__FUNCTION__.' starts now');
|
||||
|
||||
$query = 'SELECT c.id AS cat_id, id_uppercat';
|
||||
$query.= ', global_rank';
|
||||
// Count by date_available to avoid count null
|
||||
|
@ -569,6 +574,9 @@ FROM '.CATEGORIES_TABLE.' as c
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
$logger->debug(__FUNCTION__.' ends now in '.get_elapsed_time($start_time, get_moment()));
|
||||
|
||||
return $cats;
|
||||
}
|
||||
|
||||
|
|
|
@ -405,8 +405,10 @@ SELECT id, name, permalink, uppercats, global_rank, commentable
|
|||
}
|
||||
usort($related_categories, 'global_rank_compare');
|
||||
|
||||
if (empty($related_categories))
|
||||
if (empty($related_categories) and !is_admin())
|
||||
{
|
||||
// photo might be in the lounge? or simply orphan. A standard user should not get
|
||||
// info. An admin should still be able to get info.
|
||||
return new PwgError(401, 'Access denied');
|
||||
}
|
||||
|
||||
|
@ -2094,6 +2096,21 @@ function ws_images_checkUpload($params, $service)
|
|||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* API method
|
||||
* Empties the lounge, where photos may wait before taking off.
|
||||
* @since 12
|
||||
* @param mixed[] $params
|
||||
*/
|
||||
function ws_images_emptyLounge($params, $service)
|
||||
{
|
||||
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
|
||||
|
||||
$ret = array('count' => empty_lounge());
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* API method
|
||||
* add md5sum at photos, by block. Returns how md5sum were added and how many are remaining.
|
||||
|
|
26
install/db/160-database.php
Normal file
26
install/db/160-database.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | This file is part of Piwigo. |
|
||||
// | |
|
||||
// | For copyright and license information, please view the COPYING.txt |
|
||||
// | file that was distributed with this source code. |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
if (!defined('PHPWG_ROOT_PATH'))
|
||||
{
|
||||
die('Hacking attempt!');
|
||||
}
|
||||
|
||||
$upgrade_description = 'add lounge table';
|
||||
|
||||
pwg_query('
|
||||
CREATE TABLE `'.PREFIX_TABLE.'lounge` (
|
||||
`image_id` mediumint(8) unsigned NOT NULL,
|
||||
`category_id` smallint(5) unsigned NOT NULL,
|
||||
PRIMARY KEY (`image_id`,`category_id`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8
|
||||
;');
|
||||
|
||||
echo "\n".$upgrade_description."\n";
|
||||
|
||||
?>
|
|
@ -260,6 +260,17 @@ CREATE TABLE `piwigo_languages` (
|
|||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `piwigo_lounge`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `piwigo_lounge`;
|
||||
CREATE TABLE `piwigo_lounge` (
|
||||
`image_id` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||
`category_id` smallint(5) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`image_id`,`category_id`)
|
||||
) ENGINE=MyISAM;
|
||||
|
||||
--
|
||||
-- Table structure for table `piwigo_old_permalinks`
|
||||
--
|
||||
|
|
9
ws.php
9
ws.php
|
@ -769,6 +769,15 @@ function ws_addDefaultMethods( $arr )
|
|||
array('admin_only'=>true)
|
||||
);
|
||||
|
||||
$service->addMethod(
|
||||
'pwg.images.emptyLounge',
|
||||
'ws_images_emptyLounge',
|
||||
null,
|
||||
'Empty lounge, where images may be waiting before taking off.',
|
||||
$ws_functions_root . 'pwg.images.php',
|
||||
array('admin_only'=>true)
|
||||
);
|
||||
|
||||
$service->addMethod(
|
||||
'pwg.images.setInfo',
|
||||
'ws_images_setInfo',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue