Collections functions
General functions
Render functions
Theme permission functions
Resource 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 1349 to 1848

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();
        
$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);
            }

        
# 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);
            }
        }
    
# 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"] != "")
        {
        if(
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"))
        {
        if(
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))
        {
        if(isset(
$sqlset["parent"]) && $sqlset["parent"] > 0)
            {
            
$sql_where_parent_is '= ?';
            
$sql_where_parent_is_bp = ['i'$sqlset["parent"]];
            }
        else
            {
            
$sql_where_parent_is 'IS NULL';
            
$sql_where_parent_is_bp = [];
            }


        
// get FCs at the new level and re-order them
        
$fcs_after_update ps_query(
              
"SELECT DISTINCT c.ref,
                      c.`name`,
                      c.`type`,
                      c.parent,
                      c.order_by,
                      count(DISTINCT cr.resource) > 0 AS has_resources
                 FROM collection AS c
            LEFT JOIN collection_resource AS cr ON c.ref = cr.collection
                WHERE c.`type` = ?
                  AND c.parent 
{$sql_where_parent_is}
             GROUP BY c.ref"
,
            
array_merge(['i'COLLECTION_TYPE_FEATURED], $sql_where_parent_is_bp)
        );
        
usort($fcs_after_update'order_featured_collections');
        
$new_fc_level_order array_column($fcs_after_update'ref');
        
sql_reorder_records('collection'$new_fc_level_order);
        
log_activity("via save_collection({$ref})"LOG_CODE_REORDEREDimplode(', '$new_fc_level_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']);
                }
            }
        }

    
refresh_collection_frame();
    }

This article was last updated 4th February 2023 12:35 Europe/London time based on the source file dated 1st February 2023 15:00 Europe/London time.