Coding standards
Security in ResourceSpace
Developer reference
Database
Action functions
Admin functions
Ajax functions
Annotation functions
API functions
Collections functions
Comment functions
Config functions
CSV export functions
Dash functions
Debug functions
Encryption functions
Facial recognition functions
File functions
General functions
Language functions
Log functions
Login functions
Message functions
Migration functions
Node functions
PDF functions
Plugin functions
Render functions
Reporting functions
Request functions
Research functions
Slideshow functions
Theme permission functions
User functions
Video functions
Database functions
Metadata functions
Resource functions
Search functions
Map functions
Job functions
Tab functions
Test functions

save_collection()

Description

Process the save action when saving a collection

Parameters

ColumnTypeDefaultDescription
$ref integer
$coldata array array

Return

false|void

Location

include/collections_functions.php lines 1357 to 1841

Definition

 
function save_collection($ref$coldata=array())
    {
    if (!
is_numeric($ref) || !collection_writeable($ref))
        {
        return 
false;
        }
    
    if(
count($coldata) == 0)
        {
        
// Old way
        
$coldata["name"]                = getval("name","");
        
$coldata["allow_changes"]       = getval("allow_changes","") != "" 0;
        
$coldata["public"]              = getval('public',0,true);
        
$coldata["keywords"]            = getval("keywords","");
        
$coldata["result_limit"]        = getval("result_limit",0,true);
        
$coldata["relateall"]           = getval("relateall","") != "";
        
$coldata["removeall"]           = getval("removeall","") != "";
        
$coldata["deleteall"]           = getval("deleteall","") != "";
        
$coldata["users"]               = getval("users","");

        if (
checkperm("h"))
            {
            
$coldata["home_page_publish"]   = (getval("home_page_publish","") != "") ? "1" "0";
            
$coldata["home_page_text"]      = getval("home_page_text","");
            
$home_page_image getval("home_page_image",0,true);
            if (
$home_page_image 0)
                {
                
$coldata["home_page_image"] = $home_page_image;
                }
            }
        }
        
    
$oldcoldata get_collection($ref);    

    if (!
hook('modifysavecollection'))
        {
        
$sqlset = array();
        foreach(
$coldata as $colopt => $colset)
            {
            
// skip data that is not a collection property (e.g result_limit or deleteall) otherwise the $sqlset will have an
            // incorrect SQL query for the update statement.
            
if(in_array($colopt, ['result_limit''relateall''removeall''deleteall''users']))
                {
                continue;
                }

            
// Set type to public unless explicitly passed
            
if($colopt == "public" && $colset == && !isset($coldata["type"]))
                {
                
$sqlset["type"] = COLLECTION_TYPE_PUBLIC;
                }

            
// "featured_collections_changes" is determined by collection_edit.php page
            // This is meant to override the type if collection has a parent. The order of $coldata elements matters!
            
if($colopt == "featured_collections_changes" && !empty($colset))
                {
                
$sqlset["type"] = COLLECTION_TYPE_FEATURED;
                
$sqlset["parent"] = null;

                if(isset(
$colset["update_parent"]))
                    {
                    
$force_featured_collection_type = isset($colset["force_featured_collection_type"]);

                    
// A FC root category is created directly from the collections_featured.php page so not having a parent, means it's just public
                    
if($colset["update_parent"] == && !$force_featured_collection_type)
                        {
                        
$sqlset["type"] = COLLECTION_TYPE_PUBLIC;
                        }
                    else
                        {
                        
$sqlset["parent"] = (int) $colset["update_parent"];
                        }
                    }

                if(isset(
$colset["thumbnail_selection_method"]))
                    {
                    
$sqlset["thumbnail_selection_method"] = $colset["thumbnail_selection_method"];
                    }
                
                if(isset(
$colset["thumbnail_selection_method"]) || isset($colset["name"]))
                    {
                    
// Prevent the parent from being changed if user only modified the thumbnail_selection_method or name
                    
$sqlset["parent"] = (!isset($colset["update_parent"]) ? $oldcoldata["parent"] : $sqlset["parent"]);
                    }

                
// Prevent unnecessary changes
                
foreach(array("type""parent""thumbnail_selection_method") as $puc_to_prop)
                    {
                    if(isset(
$sqlset[$puc_to_prop]) && $oldcoldata[$puc_to_prop] == $sqlset[$puc_to_prop])
                        {
                        unset(
$sqlset[$puc_to_prop]);
                        }
                    }

                continue;
                }
            if(!isset(
$oldcoldata[$colopt]) || $colset != $oldcoldata[$colopt])
                {
                
$sqlset[$colopt] = $colset;
                }
            }

        
// If collection is set as private by caller code, disable incompatible properties used for COLLECTION_TYPE_FEATURED (set by the user or exsting)
        
if(isset($sqlset["public"]) && $sqlset["public"] == 0)
            {
            
$sqlset["type"] = COLLECTION_TYPE_STANDARD;
            
$sqlset["parent"] = null;
            
$sqlset["thumbnail_selection_method"] = null;
            
$sqlset["bg_img_resource_ref"] = null;
            }

        
/*
        Order by is applicable only to featured collections.
        Determine if we have to reset and, if required, re-order featured collections at the tree level

        ----------------------------------------------------------------------------------------------------------------
                                                        |     Old       |        Set        | 
                                                        |---------------|-------------------|
        Use cases                                       | Type | Parent | Type    | Parent  | Reset order_by? | Re-order?
        ------------------------------------------------|------|--------|-----------------------------------------------
        Move FC to private                              | 3    | null   | 0       | null    | yes             | no
        Move FC to public                               | 3    | any    | 4       | null    | yes             | no
        Move FC to new parent                           | 3    | null   | not set | X       | yes             | yes
        Save FC but don’t change type or parent         | 3    | null   | not set | null    | no              | no
        Save a child FC but don’t change type or parent | 3    | X      | not set | not set | no              | no
        Move public to private                          | 4    | null   | 0       | null    | no              | no
        Move public to FC (root)                        | 4    | null   | 3       | not set | yes             | yes
        Move public to FC (others)                      | 4    | null   | 3       | X       | yes             | yes
        Save public but don’t change type or parent     | 4    | null   | 4       | not set | no              | no
        Create FC at root                               | 0    | null   | 3       | not set | yes             | yes
        Create FC at other level                        | 0    | null   | 3       | X       | yes             | yes
        ----------------------------------------------------------------------------------------------------------------
        */
        // Saving a featured collection without changing its type or parent
        
$rob_cond_fc_no_change = (
            isset(
$oldcoldata['type']) && $oldcoldata['type'] === COLLECTION_TYPE_FEATURED
            
&& !isset($sqlset['type'])
            && (!isset(
$sqlset['parent']) || is_null($sqlset['parent']))
        );
        
// Saving a public collection without changing it into a featured collection
        
$rob_cond_public_col_no_change = (
            isset(
$oldcoldata['type'], $sqlset['type'])
            && 
$oldcoldata['type'] === COLLECTION_TYPE_PUBLIC
            
&& $sqlset["type"] !== COLLECTION_TYPE_FEATURED
        
);
        if( !(
$rob_cond_fc_no_change || $rob_cond_public_col_no_change) )
            {
            
$sqlset['order_by'] = 0;

            if(
                
// Type changed to featured collection
                
(isset($sqlset['type']) && $sqlset['type'] === COLLECTION_TYPE_FEATURED)

                
// Featured collection moved in the tree (ie parent changed)
                
|| ($oldcoldata['type'] === COLLECTION_TYPE_FEATURED && !isset($sqlset['type']) && isset($sqlset['parent']))
            )
                {
                
$reorder_fcs true;
                }
            }


        
// Update collection record
        
if(count($sqlset) > 0)
            {
            
$sqlupdate "";
            
$clear_fc_query_cache false;
            
$collection_columns = [
                
'name',
                
'user',
                
'created',
                
'public',
                
'allow_changes',
                
'cant_delete',
                
'keywords',
                
'savedsearch',
                
'home_page_publish',
                
'home_page_text',
                
'home_page_image',
                
'session_id',
                
'description',
                
'type',
                
'parent',
                
'thumbnail_selection_method',
                
'bg_img_resource_ref',
                
'order_by',
            ];
            
$params = [];
            foreach(
$sqlset as $colopt => $colset)
                {
                
// Only valid collection columns should be processed
                
if(!in_array($colopt$collection_columns))
                    {
                    continue;
                    }

                if(
$sqlupdate != "")
                    {
                    
$sqlupdate .= ", ";    
                    }

                if(
in_array($colopt, array("type""parent""thumbnail_selection_method""bg_img_resource_ref")))
                    {
                    
$clear_fc_query_cache true;
                    }

                if(
in_array($colopt, array("parent""thumbnail_selection_method""bg_img_resource_ref")))
                    {
                    
$sqlupdate .= $colopt " = ";
                    if(
$colset == 0){$sqlupdate .= 'NULL';}
                    else
                        {
                        
$sqlupdate .= '?';
                        
$params array_merge($params,['i'$colset]);
                        }
                    
                    continue;
                    }

                if(
$colopt == 'allow_changes')
                    {
                    
$colset = (int) $colset;
                    }

                
$sqlupdate .= $colopt " = ? ";
                
$params array_merge($params, ['s'$colset]);
                }
            if(
$sqlupdate !== '')
                {
                
$sql "UPDATE collection SET {$sqlupdate} WHERE ref = ?";
                
ps_query($sqlarray_merge($params, ['i'$ref]));

                if(
$clear_fc_query_cache)
                    {
                    
clear_query_cache("featured_collections");
                    }

                
// Log the changes
                
foreach($sqlset as $colopt => $colset)
                    {
                    switch(
$colopt)
                        {
                        case 
"public";
                            
collection_log($refLOG_CODE_COLLECTION_ACCESS_CHANGED0$colset 'public' 'private');
                        break;    
                        case 
"allow_changes";
                            
collection_log($refLOG_CODE_UNSPECIFIED0,  $colset 'true' 'false' );
                        break; 
                        default;
                            
collection_log($refLOG_CODE_EDITED0,  $colopt  " = " $colset);
                        break;
                        }
                     
                    }
                }
            }
        } 
# end replace hook - modifysavecollection

    
index_collection($ref);

    
# If 'users' is specified (i.e. access is private) then rebuild users list
    
if (isset($coldata["users"]))
        {
        
$old_attached_users=ps_array("SELECT user value FROM user_collection WHERE collection=?",array("i",$ref));

        
$new_attached_users = array();
        
$removed_users = array();

        
$collection_owner_ref=ps_value(
            
"SELECT u.ref value FROM collection c LEFT JOIN user u ON c.user=u.ref WHERE c.ref=?",
            array(
"i",$ref),
            
"");
        global 
$userref;
        
$collection_owner=get_user(($collection_owner_ref == ''?$userref:$collection_owner_ref));
        
        if(
$collection_owner_ref != "")
            {
            
$old_attached_users[]=$collection_owner["ref"]; # Collection Owner is implied as attached already
            
}

        
ps_query("delete from user_collection where collection=?",array("i",$ref));
        
        
$old_attached_groups=ps_array("SELECT usergroup value FROM usergroup_collection WHERE collection=?",array("i",$ref));
        
ps_query("delete from usergroup_collection where collection=?",array("i",$ref));

        
# Build a new list and insert
        
$users=resolve_userlist_groups($coldata["users"]);
        
$ulist=array_unique(trim_array(explode(",",$users)));
        
$urefs ps_array("select ref value from user where username in (" ps_param_insert(count($ulist)) . ")"ps_param_fill($ulist"s"));
        if (
count($urefs)>0)
            {
            
$params = [];
            foreach(
$urefs as $uref)
                {
                
$params[] = $ref$params[] = $uref
                }
            
ps_query("insert into user_collection(collection,user) values " trim(str_repeat('(?, ?),'count($urefs)), ','), ps_param_fill($params'i'));
            
$new_attached_users=array_diff($urefs$old_attached_users);
            
$removed_users array_diff($old_attached_users$urefs$collection_owner_ref != "" ? array($collection_owner["ref"]) : array());
            }

        
# log this only if a user is being added
        
if($coldata["users"]!="")
            {
            
collection_log($ref,LOG_CODE_COLLECTION_SHARED_COLLECTION,0join(", ",$ulist));
            }

        
# log the removal of users / smart groups
        
$was_shared_with = array();
        if (
count($old_attached_users) > 0)
            {
            
$was_shared_with ps_array("select username value from user where ref in (" ps_param_insert(count($old_attached_users)). ")",ps_param_fill($old_attached_users,"i"));
            }
        if (
count($old_attached_groups) > 0) {
            foreach (
$old_attached_groups as $old_group) {
                
$was_shared_with[] = "Group (Smart): " ps_value("SELECT name value FROM usergroup WHERE ref = ?", array("i"$old_group), "");
            }
        }
        if (
count($urefs) == && count($was_shared_with) > 0)
            {
            
collection_log($ref,LOG_CODE_COLLECTION_STOPPED_SHARING_COLLECTION,0join(", ",$was_shared_with));
            }

        
$groups=resolve_userlist_groups_smart($users);
        
$groupnames='';
        if(
$groups!='')
            {
            
$groups=explode(",",$groups);
            if (
count($groups)>0)
                { 
                foreach (
$groups as $group)
                    {
                    
ps_query("insert into usergroup_collection(collection,usergroup) values (?,?)",array("i",$ref,"i",$group));
                    
// get the group name
                    
if($groupnames!='')
                        {
                        
$groupnames.=", ";
                        }
                    
$groupnames.=ps_value("select name value from usergroup where ref=?",array("i",$group),"");
                    }

                
$new_attached_groups=array_diff($groups$old_attached_groups);
                if(!empty(
$new_attached_groups))
                    {
                    foreach(
$new_attached_groups as $newg)
                        {
                        
$group_users=ps_array("SELECT ref value FROM user WHERE usergroup=?",array("i",$newg));
                        
$new_attached_users=array_merge($new_attached_users$group_users);
                        }
                    }
                }
            
#log this
            
collection_log($ref,LOG_CODE_COLLECTION_SHARED_COLLECTION,0$groupnames);
            }

        
# Clear user specific collection cache if user was added or removed.
        
if (count($new_attached_users) >  || count($removed_users) > 0)
            {
            
$user_caches array_unique(array_merge($new_attached_users$removed_users));
            foreach (
$user_caches as $user_cache)
                {
                
clear_query_cache('collection_access' $user_cache);
                }
            }
        }

    
# Send a message to any new attached user
    
if(!empty($new_attached_users))
        {
        global 
$baseurl$lang;

        
$new_attached_users=array_unique($new_attached_users);
        
$message_text str_replace(
                array(
'%user%''%colname%'),
                array(
$collection_owner["fullname"]??$collection_owner["username"],getval("name","")),
                
$lang['collectionprivate_attachedusermessage']
        );
        
$message_url $baseurl "/?c=" $ref;
        
message_add($new_attached_users,$message_text,$message_url);
        }

    
# Relate all resources?
    
if (
        isset(
$coldata["relateall"]) && $coldata["relateall"] != ""
        
&& allow_multi_edit($ref)
        ) {
            
relate_all_collection($ref);
        }

    
# Remove all resources?
    
if (isset($coldata["removeall"]) && $coldata["removeall"]!="")
        {
        
remove_all_resources_from_collection($ref);
        }

    
# Delete all resources?
    
if (
        isset(
$coldata["deleteall"]) && $coldata["deleteall"]!="" && !checkperm("D")
        && 
allow_multi_edit($ref)
        ) {
            
delete_resources_in_collection($ref);
        }

    
# Update limit count for saved search
    
if (isset($coldata["result_limit"]) && (int)$coldata["result_limit"] > 0)
        {
        
ps_query("update collection_savedsearch set result_limit=? where collection=?",array("i",$coldata["result_limit"],"i",$ref));
        }

    
// Re-order featured collections tree at the level of this collection (if applicable - only for featured collections)
    
if(isset($reorder_fcs))
        {
        
$new_fcs_order reorder_all_featured_collections_with_parent($sqlset['parent'] ?? null);
        
log_activity("via save_collection({$ref})"LOG_CODE_REORDEREDimplode(', '$new_fcs_order), 'collection');
        }

    
// When a collection is now saved as a Featured Collection (must have resources) under an existing branch, apply all 
    // the external access keys from the categories which make up that path to prevent breaking existing shares.
    
if(
        isset(
$sqlset['parent']) && $sqlset['parent'] > 0
        
&& !empty($fc_resources array_filter((array) get_collection_resources($ref)))
    )
        {
        
// Delete old branch path external share associations as they are no longer relevant
        
$old_branch_category_ids array_column(get_featured_collection_category_branch_by_leaf((int) $oldcoldata['parent'], []), 'ref');
        foreach(
$old_branch_category_ids as $fc_category_id)
            {
            
$old_keys get_external_shares([
                    
'share_collection' => $fc_category_id,
                    
'share_type' => 0,
                    
'ignore_permissions' => true
                
]);
            foreach(
$old_keys as $old_key_data)
                {
                
// IMPORTANT: we delete the keys associated with the collection we've just saved. The key may still be valid for the rest of the branch categories.
                
delete_collection_access_key($ref$old_key_data['access_key']);
                }
            }


        
// Copy associations of all branch parents and apply to this collection and its resources
        
$all_branch_path_keys = [];
        
$branch_category_ids array_column(get_featured_collection_category_branch_by_leaf($sqlset['parent'], []), 'ref');
        foreach(
$branch_category_ids as $fc_category_id)
            {
            
$all_branch_path_keys array_merge(
                
$all_branch_path_keys,
                
get_external_shares([
                    
'share_collection' => $fc_category_id,
                    
'share_type' => 0,
                    
'ignore_permissions' => true
                
]));
            }

        foreach(
$all_branch_path_keys as $external_key_data)
            {
            foreach(
$fc_resources as $fc_resource_id)
                {
                if(!
can_share_resource($fc_resource_id))
                    {
                    continue;
                    }

                
ps_query(
                    
'INSERT INTO external_access_keys(resource, access_key, collection, `user`, usergroup, email, `date`, access, expires, password_hash) VALUES (?, ?, ?, ?, ?, ?, NOW(), ?, ?, ?)',
                    [
                        
'i'$fc_resource_id,
                        
's'$external_key_data['access_key'],
                        
'i'$ref,
                        
'i'$GLOBALS['userref'],
                        
'i'$external_key_data['usergroup'],
                        
's'$external_key_data['email'],
                        
'i'$external_key_data['access'],
                        
's'$external_key_data['expires'] ?: null,
                        
's'$external_key_data['password_hash'] ?: null
                    
]
                );
                
collection_log($refLOG_CODE_COLLECTION_SHARED_RESOURCE_WITH$fc_resource_id$external_key_data['access_key']);
                }
            }
        }
    global 
$userref;
    
clear_query_cache('collection_access' $userref);
    
refresh_collection_frame();
    }

This article was last updated 4th December 2024 08:35 Europe/London time based on the source file dated 27th November 2024 15:30 Europe/London time.