issue #2560 people backend and API

This commit is contained in:
Linty committed 2026-10-20 11:56:45 +02:00
1 parent e0576fddfc
commit ee66b85aed
5 files changed
+591

No files matched your search

+1
View File
@@ -360,6 +360,7 @@ if ( !$conf['allow_html_descriptions'] )
add_event_handler('render_comment_content', 'render_comment_content');
add_event_handler('render_comment_author', 'strip_tags');
add_event_handler('render_tag_url', 'str2url');
add_event_handler('render_person_url', 'str2url');
add_event_handler('blockmanager_register_blocks', 'register_default_menubar_blocks', EVENT_HANDLER_PRIORITY_NEUTRAL-1);
if ( !empty($conf['original_url_protection']) )
{
+1
View File
@@ -21,6 +21,7 @@ include_once( PHPWG_ROOT_PATH .'include/functions_url.inc.php' );
include_once( PHPWG_ROOT_PATH .'include/derivative_params.inc.php');
include_once( PHPWG_ROOT_PATH .'include/derivative_std_params.inc.php');
include_once( PHPWG_ROOT_PATH .'include/derivative.inc.php');
include_once( PHPWG_ROOT_PATH .'include/functions_people.inc.php' );
/**
+330
View File
@@ -0,0 +1,330 @@
<?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. |
// +-----------------------------------------------------------------------+
/**
* @package functions\tag
*/
/**
* Returns all people for ws functions.
*
* @param array $params
* - string search (optional)
* - is_visible (optional)
* - per_page
* - page
* @return array [id, name, url_name]
*/
function ws_get_people(array $params)
{
$where_clauses = array();
// build where clauses
if (isset($params['is_visible']))
{
$where_clauses[] = 'p.is_visible = \'' . boolean_to_string($params['is_visible']) . '\'';
}
if (!empty($params['search']))
{
$where_clauses[] = 'p.name LIKE \'%'.pwg_db_real_escape_string($params['search']).'%\'';
}
$where_sql = count($where_clauses) > 0
? 'WHERE ' . implode(' AND ', $where_clauses)
: '';
// build pagination
$per_page = intval($params['per_page']);
$page = intval($params['page']);
$offset = $page * $per_page;
// queries
$query = '
SELECT
p.*,
COUNT(ip.image_id) AS photos
FROM '.PERSONS_TABLE.' AS p
LEFT JOIN '.IMAGE_PERSON_TABLE.' AS ip ON ip.person_id = p.id
'. $where_sql .'
GROUP BY p.id
ORDER BY p.id DESC
LIMIT ' . $per_page . '
OFFSET ' . $offset . '
;';
$people = query2array($query);
$query = '
SELECT COUNT(*) AS nb
FROM ' . PERSONS_TABLE .' AS p
'. $where_sql .'
;';
$count_result = pwg_db_fetch_assoc(pwg_query($query));
$total_count = intval($count_result['nb']);
return array(
'paging' => array(
'page' => $page,
'per_page' => $per_page,
'total' => $total_count,
'total_pages' => ceil($total_count / $per_page),
),
'people' => $people,
);
}
function get_person_by_id(int $id)
{
$query = '
SELECT *
FROM '.PERSONS_TABLE.'
WHERE id = '.$id.'
;';
$result = pwg_query($query);
if (pwg_db_num_rows($result) == 0)
{
return null;
}
return pwg_db_fetch_assoc($result);
}
function get_person_by_user_id(int $user_id)
{
$query = '
SELECT *
FROM '.PERSONS_TABLE.'
WHERE user_id = '.$user_id.'
;';
$result = pwg_query($query);
if (pwg_db_num_rows($result) == 0)
{
return null;
}
return pwg_db_fetch_assoc($result);
}
function get_person_in_image_by_id(int $id)
{
$query = '
SELECT *
FROM '.IMAGE_PERSON_TABLE.'
WHERE id = '.$id.'
;';
$result = pwg_query($query);
if (pwg_db_num_rows($result) == 0)
{
return null;
}
return pwg_db_fetch_assoc($result);
}
function get_total_people()
{
$query = '
SELECT COUNT(*) as nb
FROM '.PERSONS_TABLE.'
;';
$count_result = pwg_db_fetch_assoc(pwg_query($query));
return intval($count_result['nb']);
}
/**
* Create a person.
*/
function create_person(string $name, ?int $user_id = null, bool $is_visible = true, string $source = 'manual')
{
$user_id_sql = $user_id === null ? 'NULL' : $user_id;
$name = strip_tags($name);
$query = '
INSERT INTO '.PERSONS_TABLE.'
(name, url_name, user_id, is_visible, source)
VALUES (
\''.pwg_db_real_escape_string($name).'\',
\''.pwg_db_real_escape_string(trigger_change('render_person_url', $name)).'\',
'.$user_id_sql.',
\''.boolean_to_string($is_visible).'\',
\''.pwg_db_real_escape_string($source).'\'
)
;';
pwg_query($query);
$new_person_id = pwg_db_insert_id();
pwg_activity('people', $new_person_id, 'add');
return array(
'id' => $new_person_id,
);
}
function edit_person(int $id, array $data)
{
$validated_data = [];
$person = get_person_by_id($id);
if (!$person)
{
return array('code' => 404, 'error' => 'Person not found.');
}
// name
if (!empty($data['name']))
{
$name = strip_tags($data['name']);
$validated_data['name'] = pwg_db_real_escape_string($name);
$validated_data['url_name'] = pwg_db_real_escape_string(trigger_change('render_person_url', $name));
}
// is_visible
if (isset($data['is_visible']))
{
if (!is_bool($data['is_visible']))
{
return array('code' => 403, 'error' => 'is_visible must be: true or false.');
}
$validated_data['is_visible'] = boolean_to_string($data['is_visible']);
}
// source
if (!empty($data['source']))
{
if (!validate_people_source($data['source']))
{
return array('code' => 403, 'error' => 'source must be: manual, auto or imported.');
}
$validated_data['source'] = $data['source'];
}
// user_id, 0 dissociates the user
if (isset($data['user_id']))
{
if (!preg_match('/^\d+$/', $data['user_id']))
{
return array('code' => 403, 'error' => 'user_id must be a digit.');
}
if (0 == $data['user_id'])
{
$validated_data['user_id'] = null;
}
else if ($person['user_id'] != $data['user_id'])
{
$is_user_already_associated = get_person_by_user_id($data['user_id']);
if ($is_user_already_associated)
{
return array('code' => 401, 'error' => 'This user is already associated with a person.');
}
$validated_data['user_id'] = $data['user_id'];
}
}
// cover_image_person_id
if (!empty($data['cover_image_person_id']))
{
if (!preg_match('/^\d+$/', $data['cover_image_person_id']))
{
return array('code' => 403, 'error' => 'cover_image_person_id must be a digit.');
}
$cover_exist = get_person_in_image_by_id($data['cover_image_person_id']);
if (!$cover_exist)
{
return array('code' => 404, 'error' => 'Person in image not found.');
}
$validated_data['cover_image_person_id'] = $data['cover_image_person_id'];
}
// save data
if (count($validated_data) === 0)
{
return true;
}
single_update(
PERSONS_TABLE,
$validated_data,
array('id' => $id)
);
pwg_activity('people', $person['id'], 'edit');
return true;
}
/**
* @param int[]|int $people_ids
* @return bool
*/
function delete_people($people_ids)
{
if (is_numeric($people_ids))
{
$people_ids = array($people_ids);
}
if (!is_array($people_ids))
{
return false;
}
// we need the list of impacted images, to update their lastmodified like tags
$query = '
SELECT
image_id
FROM '.IMAGE_PERSON_TABLE.'
WHERE person_id IN ('.implode(',', $people_ids).')
;';
$image_ids = query2array($query, null, 'image_id');
$query = '
DELETE
FROM '.IMAGE_PERSON_TABLE.'
WHERE person_id IN ('.implode(',', $people_ids).')
;';
pwg_query($query);
$query = '
DELETE
FROM '.PERSONS_TABLE.'
WHERE id IN ('.implode(',', $people_ids).')
;';
pwg_query($query);
pwg_activity('people', $people_ids, 'delete');
update_images_lastmodified($image_ids);
return true;
}
function merge_people() {}
// utils
function validate_people_source(string $source)
{
if (!in_array($source, ['manual', 'imported', 'auto']))
{
return false;
}
return true;
}
+148
View File
@@ -0,0 +1,148 @@
<?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. |
// +-----------------------------------------------------------------------+
/**
* API method
* Returns a list of people
* @param mixed[] $params
* @option int[] user_id (optional)
* @option string username (optional)
* @option string[] status (optional)
* @option int min_level (optional)
* @option int max_level (optional)
* @option int[] group_id (optional)
* @option int per_page
* @option int page
* @option string order
* @option string display
* @option string filter
* @option int[] exclude (optional)
* @option string min_register
* @option string max_register
*/
function ws_people_getList($params, &$service)
{
}
/**
* API method
* Returns the list of people as you can see them in administration
* @param mixed[] $params
*
* Only admin can run this method and permissions are not taken into
* account.
*/
function ws_people_getAdminList($params, &$service)
{
$people = ws_get_people($params);
$people['total_people'] = get_total_people();
return $people;
}
/**
* API method
* Add a person
* @param mixed[] $params
* @option string name
* @option bool is_visible
*/
function ws_people_add($params, &$service)
{
if (get_pwg_token() != $params['pwg_token'])
{
return new PwgError(403, 'Invalid security token');
}
if (!validate_people_source($params['source']))
{
return new PwgError(403, 'source must be: manual, auto or imported.');
}
if ('' === trim(strip_tags($params['name'])))
{
return new PwgError(WS_ERR_INVALID_PARAM, 'name must not be empty.');
}
$new_person = create_person(
$params['name'],
null, // not a created_by user_id but associated with user_id
$params['is_visible'],
$params['source']
);
return array(
'id' => $new_person['id'],
);
}
/**
* API method
* Edit a person
* @param mixed[] $params
* @option int id
* @option string name
*/
function ws_people_edit($params, &$service)
{
if (get_pwg_token() != $params['pwg_token'])
{
return new PwgError(403, 'Invalid security token');
}
$is_edited = edit_person($params['person_id'], $params);
if (isset($is_edited['error']))
{
return new PwgError($is_edited['code'], $is_edited['error']);
}
return array(
'id' => $params['person_id'],
);
}
/**
* API method
* Delete a person
* @param mixed[] $params
* @option int id
*/
function ws_people_delete($params, &$service)
{
include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
if (get_pwg_token() != $params['pwg_token'])
{
return new PwgError(403, 'Invalid security token');
}
$people_ids = $params['people_ids'];
$query = '
SELECT COUNT(*)
FROM `'. PERSONS_TABLE .'`
WHERE id in ('.implode(',', $people_ids) .')
;';
list($count) = pwg_db_fetch_row(pwg_query($query));
if ($count != count($people_ids))
{
return new PwgError(401, 'All people does not exist.');
}
if (count($people_ids) > 0)
{
delete_people($people_ids);
return array( 'id' => $people_ids );
} else {
return array( 'id' => array() );
}
}
+111
View File
@@ -1709,6 +1709,117 @@ enabled_high, registration_date, registration_date_string, registration_date_sin
'post_only'=>true
)
);
$service->addMethod(
'pwg.people.getAdminList',
'ws_people_getAdminList',
array(
'search' => array(
'default' => null,
'flags' => WS_PARAM_OPTIONAL,
),
'is_visible' => array(
'type' => WS_TYPE_BOOL,
'flags' => WS_PARAM_OPTIONAL,
),
'per_page' => array(
'default' => 50,
'maxValue' => 1000,
'type' => WS_TYPE_INT|WS_TYPE_POSITIVE,
),
'page' => array(
'default' => 0,
'type' => WS_TYPE_INT|WS_TYPE_POSITIVE,
),
),
'<b>Admin only.</b>',
$ws_functions_root . 'pwg.people.php',
array(
'hidden' => false,
'post_only' => false,
'admin_only' => true,
)
);
$service->addMethod(
'pwg.people.add',
'ws_people_add',
array(
'name' => array(),
'is_visible' => array(
'type' => WS_TYPE_BOOL,
),
'source' => array(
'default' => 'manual',
'info' => 'manual,auto,imported'
),
'pwg_token' => array(),
),
'Add a new person.',
$ws_functions_root . 'pwg.people.php',
array(
'hidden' => false,
'post_only' => true,
'admin_only' => true,
)
);
$service->addMethod(
'pwg.people.edit',
'ws_people_edit',
array(
'person_id' => array(
'type' => WS_TYPE_ID,
),
'name' => array(
'flags' => WS_PARAM_OPTIONAL,
),
'is_visible' => array(
'type' => WS_TYPE_BOOL,
'flags' => WS_PARAM_OPTIONAL,
),
'source' => array(
'flags' => WS_PARAM_OPTIONAL,
'info' => 'manual,auto,imported'
),
'user_id' => array(
'type' => WS_TYPE_INT|WS_TYPE_POSITIVE,
'flags' => WS_PARAM_OPTIONAL,
'info' => '0 to dissociate the user',
),
'cover_image_person_id' => array(
'type' => WS_TYPE_ID,
'flags' => WS_PARAM_OPTIONAL,
),
'pwg_token' => array(),
),
'Edit a person.',
$ws_functions_root . 'pwg.people.php',
array(
'hidden' => false,
'post_only' => true,
'admin_only' => true,
)
);
$service->addMethod(
'pwg.people.delete',
'ws_people_delete',
array(
'people_ids' => array(
'type' => WS_TYPE_ID,
'flags' => WS_PARAM_FORCE_ARRAY,
),
'pwg_token' => array(),
),
'Delete people by ID.',
$ws_functions_root . 'pwg.people.php',
array(
'hidden' => false,
'post_only' => true,
'admin_only' => true,
)
);
}
?>