Advanced: Programmatically Setting Permissions on a File Manager's Folder

Change Permissions on a Folder

As previously explained, when setting permissions on any object, we first must enable Advanced Permissions via the dashboard.

Getting a Folder Object

To work on a Folder we first require a Folder Object. Here are 3 ways of getting one depending on your use case. In each one the variable $folderObject will contain the Folder Object we want to set permissions on.

Creating a new folder at the root

<?php
use Concrete\Core\File\Filesystem;
use Concrete\Core\Tree\Node\Type\FileFolder;

$fileSystem = new Filesystem();
$root = $fileSystem->getRootFolder();
$folderObject = FileFolder::add('Test Folder', $root);

Getting a folder by name

<?php
use Concrete\Core\Tree\Node\Node;

$folderObject = Node::getNodeByName('Test Folder');

Getting a folder by name and creating it at the root if it doesn't exist

<?php
use Concrete\Core\File\Filesystem;
use Concrete\Core\Tree\Node\Type\FileFolder;

$fileSystem = new Filesystem();
$root = $fileSystem->getRootFolder();
// The second parameter in the getChildFolderByName() method tells it to create the folder if needed
$folderObject = $root->getChildFolderByName('Test Folder', true);

Of course you can use the same code to add or grab a folder inside any other folder.

Setting permissions

Now that we have our Folder Object, let's add permissions to it. We are interested in removing viewing permisisons for non-logged-in guest users.

The permission key for Folders viewing permissions uses the handle view_file_folder_file The ID for the Guest user group is GUEST_GROUP_ID

<?php
use Concrete\Core\Permission\Access\Entity\GroupEntity;
use Concrete\Core\User\Group\Group;
use Concrete\Core\Permission\Key\Key;
use Concrete\Core\Permission\Access\Access;

// First we override permissions our folder inherited from its parent folder
folderObject->setTreeNodePermissionsToOverride();
// We then grab an Access Group Entity for the guest User Group
$permissionEntity = GroupEntity::getOrCreate(Group::getByID(GUEST_GROUP_ID));
// We get our viewing permission key
$permissionKey = Key::getByHandle('view_file_folder_file');
// And we assign it our Folder Object
$permissionKey->setPermissionObject($folderObject);

/*So far our object still uses the permissions inherited from its parent.
Because we want to add to those and not remove them altogether, we need to make sure
we include them in a new custom Permission Access Object (we'll see that later below.)
So first lets grab the existing permission Assignment Object from our permission key.
As the name says it includes information on how permissions are assigned. */
$permissionAssignmentObject = $permissionKey->getPermissionAssignmentObject();

/*Then we get the permissions list. We want permissions for all access types: inclusions and exclusions
Our 3 choices are ACCESS_TYPE_INCLUDE, ACCESS_TYPE_EXCLUDE, and ACCESS_TYPE_ALL 
What we see here is a clear hierarchy:
Permission Key (referencing our folder object) -> Permission Assignment -> Permission Access -> Access Items */
$accessListItems = $permissionAssignmentObject->getPermissionAccessObject()->getAccessListItems(Key::ACCESS_TYPE_ALL);

/*If we added our new Access Item to our Folder Object's existing Permission Access Object,
we would also impact the root folder's permissions. 
So we create a new one, assign it the existing Permission Access Object and add the new list item to it. */
$permissionAccessObject = Access::create($permissionKey);

/* We now add our existing Access Items to our new Permission Access Object.
For example, by default, the Administrators group is included in the viewing permission
and we want to keep it that way so we add all existing permissions back */
foreach($accessListItems as $accessListItem) {
    /*
    An Access List Item has 3 pieces of information we need:
    1- An Access Entity Object (what User or User Group)
    2- A Permission Duration Object (when limited in time)
    3- An Access Type (inclusion or exclusion)
    */
    $permissionAccessObject->addListItem($accessListItem->getAccessEntityObject(), $accessListItem->getPermissionDurationObject(), $accessListItem->getAccessType());
}

/*
We now add our specific permission rule to the list (the one we've been meaning to add all along):
Excluding (ACCESS_TYPE_EXCLUDE) the GUEST group ($permissionEntity) from the Viewing Folders permission.
The second parameter of the addListItem() could be a Duration Object if required. It's set to false for no duration.
*/
$permissionAccessObject->addListItem($permissionEntity, false, Key::ACCESS_TYPE_EXCLUDE);

/* And finally we add our new Permission Access Object 
to the Permission Assignment Object we grabbed earlier from our Permission Key.
It replaces the existing one. */
$permissionAssignmentObject->assignPermissionAccess($permissionAccessObject);

Here's the hierarchy or Permission objects again:

  • A Permission Key Concrete\Core\Permission\Key\Key referencing our folder object
    • A Permission Assignment Object Concrete\Core\Permission\Assignment\Assignment
      • A Permission Access Object Concrete\Core\Permission\Access\Access
        • Access Items, an array of Access List Item Objects Concrete\Core\Permission\Access\ListItem\ListItem