Aller au contenu

omnibase/drive Référence de l’API

Étage
Structure préparée · Omnibase
Version
main
Vérifié en réel
Son README ne le dit pas
Licence
MIT
composer require omnibase/drive:dev-main

Lue dans les fichiers PHP du paquet au commit 74eceb1c44f1 : ses espaces de noms, classes, interfaces et énumérations, leurs constantes, propriétés et méthodes publiques avec leur PHPDoc, et les options que prennent ses fabriques. Rien n’en est exécuté.

Base\Drive

  • DriveBundle class

    The drive application on top of omnibase: a site's own cloud of folders and files (FileShare), who each folder is for (the audiences), whom it is shared with by name, workspaces with their people and tasks, search, previews, zips and download counts - on the site's storage, or its Google Drive once connected from the back office.

    3 methods

Base\Drive\Audience

  • AudienceInterface interface

    Who a folder or a file of the drive is for (SharedPath::$audience holds its key): the bundle's readers, users, members and staff, and whatever a site or another bundle adds - the associates of a company (omnibase/estate's), a studio's customers. A service implementing it is one more choice in « Pour qui », tagged drive.audience by autoconfiguration.

    4 methods · 1 constant

  • Audiences class

    Every audience of the drive (AudienceInterface, tagged drive.audience), by key, in the order of « Pour qui »: the bundle's (readers, users, members), the site's, then staff last. A key no audience answers to any more (a site that removed one) is read as the staff's: nobody else sees what was for it.

    6 methods

  • MembersAudience class

    A path for the people of the workspace the path is in (the folder made one, and its people).

    4 methods · 1 constant

  • ReadersAudience class

    A path for everyone, signed in or not.

    4 methods · 1 constant

  • StaffAudience class

    A path for the staff only (who see everything anyway): nobody else.

    4 methods · 1 constant

  • UsersAudience class

    A path for the signed-in accounts.

    4 methods · 1 constant

Base\Drive\Command

  • CountCommand class

    A path's downloads in the drive set at a number - the ones counted elsewhere before (an old download page's statistics); --add adds to what it has. A path no longer there may count too: a version gone, its downloads kept in its folder's total.

    1 method

  • ImportCommand class

    A folder of files into the drive (Base\Drive\Share\FileShare), as it is: its tree under `target` (the root by default). Hidden files (.git, .htaccess) stay behind; a file already there with the same size is left; one of another size is replaced, unless the retention lock keeps it (drive.retention: left as it is, and said). For what is too big or too many to upload from the page.

    1 method

  • MoveCommand class

    Files and folders of the drive moved into another folder (a workspace, say): what was said of them and their downloads follow. --tags drops their own tags (their new folder's are theirs now). Nothing moves out of a folder the retention lock keeps (drive.retention).

    1 method

  • WorkspaceCommand class

    A workspace of the drive from the command line: a new folder at its root - or one already there, made a workspace -, who it is for, a few words on it, its tags.

    1 method

Base\Drive\Controller

  • ShareController class

    The drive's page (Base\Drive\Share\FileShare): files shared with the readers, the users, the people of a workspace and whoever the site's audiences let in, as an index of files - a folder lists what it holds (its README under it), a file opens, shows (?preview) or downloads, a folder downloads as a zip (?zip) - never the drive as a whole; a search through every folder (?q); someone the root is not for has a root of their own. Who sees what is ShareVoter's; the staff manage it on the page itself: upload (a dropped folder kept whole), a new folder, who a folder is for, whom it is shared with, a few words on it, move, rename, delete. Files added by the team may be shared at once with named people and groups (share_with[]): a copy in each one's space (Space\Spaces). With the retention lock on (drive.retention), nothing locked is deleted, renamed nor moved, and the superadmin lifts a folder's lock and puts it back from its access dialog, where the log is listed.

    3 methods

Base\Drive\Controller\Admin

  • DriveController class

    The drive's Google Drive, from the back office: connect the site's Google account, pick (or create) the folder the files live in, lay out the site's folders (TreeInterface, when it has one), disconnect. Until then the files stay on the site's storage, and move nowhere by themselves. Loaded with omnibase/admin and google/apiclient (config/services.php).

    7 methods

Base\Drive\DependencyInjection

Base\Drive\Entity

  • PersonalTag class

    A tag someone put on a folder for themselves (Base\Drive\Share\PersonalTags, drive.personal_tags): theirs alone - nobody else sees it, the team neither -, to sort what they see as they like. Its colour is theirs too, the same on every folder they gave that tag.

    8 methods

  • RetentionEvent class

    One line of the retention log (drive.retention, Base\Drive\Share\Retention): a folder's lock lifted - until it is put back, or until a date -, or put back, by whom, when and why. The log is only ever added to: a folder's state is its latest line (a lift that is still running, or locked), a lift whose date has passed being a lock again by itself.

    11 methods · 2 constants

  • ShareDownload class

    How many times a file of the drive was downloaded (Base\Drive\Controller\ShareController) - or a folder, as a zip, or the old downloads of versions no longer there (drive:count). A number per path and when it last grew: nothing of who downloaded it.

    6 methods

  • ShareGroup class

    A group of people the team names - a flatshare's tenants, a couple, a family's heirs - to share folders with all of them at once (SharedPath::$groups): whoever is in it sees what is shared with it, as if shared with them by name; someone added later sees it too, someone taken out no longer does.

    9 methods

  • ShareTask class

    A task of a workspace of the drive (SharedPath::$tasks): a few words, done or not - and when, and who wrote it.

    12 methods

  • SharedPath class

    What the team says of a folder or a file of the drive (Base\Drive\Share\FileShare): who it is for (an audience's key: Base\Drive\Audience), a few words shown above its list, its tags (what is under it has them too), whether it is listed. A folder may be a workspace: its people (members: they see it whoever else it is for, and what is "for its members" is for them) and its tasks. The files themselves are on the storage; a path without a row here is as its nearest parent with one - the root as drive.default_audience says.

    26 methods

Base\Drive\People

  • AccountPeople class

    The drive's people by default: every account of drive.user_class, by its identifier and its e-mail, in one group ("accounts").

    3 methods

  • PeopleInterface interface

    Whom a folder of the drive may be shared with, by name and what they are to the site: groups of accounts (user id => label). The bundle's AccountPeople lists every account; a site says who its people are with its own implementation and #[AsAlias(PeopleInterface::class)] - omnibase/estate's tenants, associates, contractors and team for a property company. Each group's name is a translation key of the messages domain: share.people_group.<group>.

    2 methods

Base\Drive\Repository

Base\Drive\Security\Voter

  • ShareVoter class

    Who sees a path of the drive (SHARE_VIEW, the path as subject), who manages it (SHARE_MANAGE: the staff, drive.staff_role), and who works in a workspace - its tasks, the files its people bring (SHARE_WORK, the path as subject: its members and the staff). A path is for its audience (FileShare::audience, answered by Base\Drive\Audience\Audiences: the readers, the signed-in users, the members of its workspace, the staff only, and the site's own); and, whatever its audience, for the people it was shared with (FileShare::isSharedWith: a workspace's people, in it or above it).

    1 method · 5 constants

Base\Drive\Share

  • FileShare class

    The drive (« le Partage », « Cloud » on a site's pages): files a site shares with its readers, its users, the people of its workspaces and whoever its own audiences let in - an index of files, as a web server's "Index of /", with a little more: who each folder is for, whom it is shared with by name, a few words above it, its README under it, a search through the tree, each person's own root.

    39 methods · 2 constants

  • LockedException class

    What the retention lock refuses (drive.retention): deleting, overwriting, renaming or moving something in a locked folder - whoever asks, the team included.

    1 method · 1 property

  • PersonalTags class

    The tags each one puts on folders for themselves (drive.personal_tags): a tenant sorting their papers, an owner theirs, nobody else seeing them. Like the team's tags, a folder's apply to what it holds (to filter by). Nothing when the option is off or nobody is signed in; their rows follow a folder moved and go with one deleted (FileShare).

    10 methods

  • Retention class

    The retention lock (drive.retention, off by default): with it on, every folder of the drive and what it holds is kept - nothing deleted, overwritten, renamed nor moved, by anyone, the team included (FileShare refuses it, ShareVoter's SHARE_ALTER says no). Adding files stays open.

    12 methods

  • TagColors class

    A tag's colour, the same wherever the tag is shown: the one the team chose for it (kept in the site's settings, app.drive.tag_colors, by the tag's key), otherwise one of a few drawn from its name - so that a tag has a colour of its own before anyone chooses.

    4 methods · 1 constant

Base\Drive\Space

  • SpaceProviderInterface interface

    Where a person's space is in the drive: the folder their role gives them - a tenant's, an owner's, a partner's. A bundle that knows its people implements it (omnibase/estate: Locataires/<tenant>, Propriétaires/<owner>, Indivisions/<ownership>), tagged drive.space by autoconfiguration; the providers are asked in their priority's order, the first to answer wins, and nobody answering leaves the drive's own place (Spaces: drive.spaces_root/<name>).

    1 method · 1 constant

  • Spaces class

    Each person's space in the drive, and files shared on upload with named people: a file added goes, besides the folder it was added to, into the space of each person named - and of each person of a group named (Entity\ShareGroup) -, the space made if missing, reused otherwise, shared with them read only unless the uploader lets them bring files too.

    3 methods

Base\Drive\Storage

  • DocumentsStorage class

    Where the drive's files are (the service drive.storage, alias documents.storage, read by Base\Drive\Share\FileShare): the site's Google Drive folder once connected from the back office (google/apiclient and masbug/flysystem-google-drive-ext installed), the site's own storage otherwise (drive.local_storage, local.share by default) - and always in the tests.

    3 methods

  • DriveClient class

    Google, for the documents: the consent screen (offline access, the whole Drive - so files dropped into the folder from Drive itself show up), and a Drive service on the stored refresh token. The OAuth client is the site's (GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET); its consent screen must be published, or Google drops the token after seven days.

    6 methods

  • DriveSettings class

    What the site keeps of its Google Drive: the refresh token (encrypted with the app secret: it opens the whole Drive), the folder the documents live in, and who connected it. In omnibase's settings, under the names the sites stored them with (app.drive.*), sealed with the same key: a Drive connected before the bundle stays connected.

    10 methods

Base\Drive\Tree

  • DocumentsTree class

    A site's layout of folders (TreeInterface) created where the files are (its storage or its Google Drive): each folder missing made, who each is for set at the same time. Folders already there are left as they are, and so is what they hold.

    2 methods

  • TreeInterface interface

    A site's own layout of folders, laid out where the files are (its storage or its Google Drive) by DocumentsTree - from the back office's Google Drive page (« Créer les dossiers ») or the site's fixtures. A property company's: its statutes, general meetings, accounts, a folder per home. The page offers it only when the site has one: a service implementing this interface, aliased with #[AsAlias(TreeInterface::class)].

    2 methods

Base\Drive\Twig

  • DriveExtension class

    For a site's templates: drive_tag_color(tag), a team's tag's colour (Share\TagColors); drive_my_tag_color(tag), the colour of a tag of one's own (Share\PersonalTags); path|drive_slug, a path as the drive's addresses read it (drive.slugs: its slugs, otherwise itself) - for path('app_share', {path: entry.path|drive_slug}).

    3 methods

Base\Drive

DriveBundle class

class DriveBundle extends AbstractBaseBundle DriveBundle.php:15

The drive application on top of omnibase: a site's own cloud of folders and files (FileShare), who each folder is for (the audiences), whom it is shared with by name, workspaces with their people and tasks, search, previews, zips and download counts - on the site's storage, or its Google Drive once connected from the back office.

DriveBundle::__construct()

public function __construct()

DriveBundle::getPath()

public function getPath(): string

The bundle root is the package root: ./templates is @Drive, ./src/Entity is mapped.

DriveBundle::build()

public function build(ContainerBuilder $container): void

Base\Drive\Audience

AudienceInterface interface

interface AudienceInterface AudienceInterface.php:15

Who a folder or a file of the drive is for (SharedPath::$audience holds its key): the bundle's readers, users, members and staff, and whatever a site or another bundle adds - the associates of a company (omnibase/estate's), a studio's customers. A service implementing it is one more choice in « Pour qui », tagged drive.audience by autoconfiguration.

const TAG = 'drive.audience'

AudienceInterface::key()

public function key(): string

What sharedPath.audience holds: lower case, 16 characters at most ("readers", "associates").

AudienceInterface::label()

public function label(): string

Its name, a translation key of the messages domain ("share.audience.readers").

AudienceInterface::icon()

public function icon(): string

Font Awesome's icon for it ("fa-solid fa-earth-europe").

AudienceInterface::lets()

public function lets(?UserInterface $user, string $path, FileShare $share): bool

Whether it lets someone see a path that is for it: $user is null when nobody is signed in.

The staff see everything anyway, and the people a path is shared with see it whatever its audience: neither is asked here.

Audiences class

final class Audiences Audiences.php:13

Every audience of the drive (AudienceInterface, tagged drive.audience), by key, in the order of « Pour qui »: the bundle's (readers, users, members), the site's, then staff last. A key no audience answers to any more (a site that removed one) is read as the staff's: nobody else sees what was for it.

Audiences::__construct()

public function __construct(readonly iterable $audiences)

Audiences::all()

public function all(): array

Audiences::has()

public function has(string $key): bool

Audiences::get()

public function get(string $key): AudienceInterface

The audience of a key - the staff's for a key nobody answers to.

Audiences::find()

public function find(?string $key): ?AudienceInterface

The audience of a key typed or posted, or null when there is none of that key.

Audiences::keys()

public function keys(): array

MembersAudience class

final class MembersAudience implements AudienceInterface MembersAudience.php:11

A path for the people of the workspace the path is in (the folder made one, and its people).

const KEY = 'members'

MembersAudience::key()

public function key(): string

MembersAudience::label()

public function label(): string

MembersAudience::icon()

public function icon(): string

MembersAudience::lets()

public function lets(?UserInterface $user, string $path, FileShare $share): bool

ReadersAudience class

final class ReadersAudience implements AudienceInterface ReadersAudience.php:10

A path for everyone, signed in or not.

const KEY = 'readers'

ReadersAudience::key()

public function key(): string

ReadersAudience::label()

public function label(): string

ReadersAudience::icon()

public function icon(): string

ReadersAudience::lets()

public function lets(?UserInterface $user, string $path, FileShare $share): bool

StaffAudience class

final class StaffAudience implements AudienceInterface StaffAudience.php:10

A path for the staff only (who see everything anyway): nobody else.

const KEY = 'staff'

StaffAudience::key()

public function key(): string

StaffAudience::label()

public function label(): string

StaffAudience::icon()

public function icon(): string

StaffAudience::lets()

public function lets(?UserInterface $user, string $path, FileShare $share): bool

UsersAudience class

final class UsersAudience implements AudienceInterface UsersAudience.php:10

A path for the signed-in accounts.

const KEY = 'users'

UsersAudience::key()

public function key(): string

UsersAudience::label()

public function label(): string

UsersAudience::icon()

public function icon(): string

UsersAudience::lets()

public function lets(?UserInterface $user, string $path, FileShare $share): bool

Base\Drive\Command

CountCommand class

final class CountCommand extends Command CountCommand.php:19

A path's downloads in the drive set at a number - the ones counted elsewhere before (an old download page's statistics); --add adds to what it has. A path no longer there may count too: a version gone, its downloads kept in its folder's total.

CountCommand::__construct()

public function __construct(readonly FileShare $share)

ImportCommand class

final class ImportCommand extends Command ImportCommand.php:20

A folder of files into the drive (Base\Drive\Share\FileShare), as it is: its tree under target (the root by default). Hidden files (.git, .htaccess) stay behind; a file already there with the same size is left; one of another size is replaced, unless the retention lock keeps it (drive.retention: left as it is, and said). For what is too big or too many to upload from the page.

ImportCommand::__construct()

public function __construct(readonly FileShare $share)

MoveCommand class

final class MoveCommand extends Command MoveCommand.php:20

Files and folders of the drive moved into another folder (a workspace, say): what was said of them and their downloads follow. --tags drops their own tags (their new folder's are theirs now). Nothing moves out of a folder the retention lock keeps (drive.retention).

MoveCommand::__construct()

public function __construct(readonly FileShare $share)

WorkspaceCommand class

final class WorkspaceCommand extends Command WorkspaceCommand.php:19

A workspace of the drive from the command line: a new folder at its root - or one already there, made a workspace -, who it is for, a few words on it, its tags.

WorkspaceCommand::__construct()

public function __construct(readonly FileShare $share, readonly Audiences $audiences)

Base\Drive\Controller

ShareController class

class ShareController extends AbstractController ShareController.php:46

The drive's page (Base\Drive\Share\FileShare): files shared with the readers, the users, the people of a workspace and whoever the site's audiences let in, as an index of files - a folder lists what it holds (its README under it), a file opens, shows (?preview) or downloads, a folder downloads as a zip (?zip) - never the drive as a whole; a search through every folder (?q); someone the root is not for has a root of their own. Who sees what is ShareVoter's; the staff manage it on the page itself: upload (a dropped folder kept whole), a new folder, who a folder is for, whom it is shared with, a few words on it, move, rename, delete. Files added by the team may be shared at once with named people and groups (share_with[]): a copy in each one's space (Space\Spaces). With the retention lock on (drive.retention), nothing locked is deleted, renamed nor moved, and the superadmin lifts a folder's lock and puts it back from its access dialog, where the log is listed.

Its path is the site's: the key app.share of its config/routes_paths.yaml (fr: /cloud/{path}), its route names app_share and app_share_manage. Its page is @Drive/share/index.html.twig, which a site overrides with its own (templates/bundles/DriveBundle/share/index.html.twig).

ShareController::__construct()

public function __construct(readonly FileShare $share, readonly TranslatorInterface $translator, readonly EntityManagerInterface $entityManager, readonly PeopleInterface $people, readonly Audiences $audiences, readonly TagColors $tagColors, readonly PersonalTags $personalTags, readonly Retention $retention, readonly Spaces $spaces, readonly string $userClass = 'App\Entity\User', readonly string $zipName = 'drive', readonly bool $listedRoot = false, readonly string $teamTags = 'everyone', readonly bool $slugs = false)

ShareController::show()

public function show(Request $request, string $path = ''): Response

ShareController::manage()

public function manage(Request $request, string $path = ''): Response

The staff's hand on a folder: upload, a new folder, who it is for and its words, delete.

Base\Drive\Controller\Admin

DriveController class

class DriveController extends AbstractController DriveController.php:25

The drive's Google Drive, from the back office: connect the site's Google account, pick (or create) the folder the files live in, lay out the site's folders (TreeInterface, when it has one), disconnect. Until then the files stay on the site's storage, and move nowhere by themselves. Loaded with omnibase/admin and google/apiclient (config/services.php).

DriveController::__construct()

public function __construct(readonly DriveSettings $settings, readonly DriveClient $client, readonly TranslatorInterface $translator, readonly ?TreeInterface $tree = null)

DriveController::index()

public function index(DocumentsStorage $storage): Response

DriveController::connect()

public function connect(Request $request): RedirectResponse

DriveController::callback()

public function callback(Request $request): RedirectResponse

DriveController::folder()

public function folder(Request $request): RedirectResponse

DriveController::tree()

public function tree(Request $request, DocumentsTree $documents): RedirectResponse

DriveController::disconnect()

public function disconnect(Request $request): RedirectResponse

Base\Drive\DependencyInjection

DriveConfiguration class

class DriveConfiguration implements ConfigurationInterface DriveConfiguration.php:8

DriveConfiguration::getConfigTreeBuilder()

public function getConfigTreeBuilder(): TreeBuilder

DriveExtension class

class DriveExtension extends AbstractBaseExtension DriveExtension.php:12

DriveExtension::getConfiguration()

public function getConfiguration(array $config, ContainerBuilder $container): DriveConfiguration

DriveExtension::load()

public function load(array $configs, ContainerBuilder $container): void

Base\Drive\Entity

PersonalTag class

class PersonalTag PersonalTag.php:13

A tag someone put on a folder for themselves (Base\Drive\Share\PersonalTags, drive.personal_tags): theirs alone - nobody else sees it, the team neither -, to sort what they see as they like. Its colour is theirs too, the same on every folder they gave that tag.

PersonalTag::__construct()

public function __construct(User $user, string $path, string $name, string $tagKey)

PersonalTag::getId()

public function getId(): ?int

PersonalTag::getUser()

public function getUser(): User

PersonalTag::getPath()

public function getPath(): string

PersonalTag::getName()

public function getName(): string

PersonalTag::getTagKey()

public function getTagKey(): string

PersonalTag::getColor()

public function getColor(): ?string

PersonalTag::setColor()

public function setColor(?string $color): self

RetentionEvent class

class RetentionEvent RetentionEvent.php:15

One line of the retention log (drive.retention, Base\Drive\Share\Retention): a folder's lock lifted - until it is put back, or until a date -, or put back, by whom, when and why. The log is only ever added to: a folder's state is its latest line (a lift that is still running, or locked), a lift whose date has passed being a lock again by itself.

const LIFT = 'lift'
const LOCK = 'lock'

RetentionEvent::__construct()

public function __construct(string $path, string $action, string $reason, ?User $user, \DateTimeImmutable $at, ?\DateTimeImmutable $until = null)

RetentionEvent::getId()

public function getId(): ?int

RetentionEvent::getPath()

public function getPath(): string

RetentionEvent::getAction()

public function getAction(): string

RetentionEvent::isLift()

public function isLift(): bool

RetentionEvent::getUntil()

public function getUntil(): ?\DateTimeImmutable

RetentionEvent::getReason()

public function getReason(): string

RetentionEvent::getUser()

public function getUser(): ?User

RetentionEvent::getUserName()

public function getUserName(): ?string

RetentionEvent::getAt()

public function getAt(): \DateTimeImmutable

RetentionEvent::liftsOn()

public function liftsOn(\DateTimeImmutable $now): bool

A lift still running at that moment: until it is put back, or until a date not reached yet.

ShareDownload class

class ShareDownload ShareDownload.php:13

How many times a file of the drive was downloaded (Base\Drive\Controller\ShareController) - or a folder, as a zip, or the old downloads of versions no longer there (drive:count). A number per path and when it last grew: nothing of who downloaded it.

ShareDownload::__construct()

public function __construct(string $path = '', int $count = 0)

ShareDownload::getId()

public function getId(): ?int

ShareDownload::getPath()

public function getPath(): string

ShareDownload::getCount()

public function getCount(): int

ShareDownload::setCount()

public function setCount(int $count): self

ShareDownload::getLastAt()

public function getLastAt(): ?\DateTimeImmutable

ShareGroup class

class ShareGroup ShareGroup.php:16

A group of people the team names - a flatshare's tenants, a couple, a family's heirs - to share folders with all of them at once (SharedPath::$groups): whoever is in it sees what is shared with it, as if shared with them by name; someone added later sees it too, someone taken out no longer does.

ShareGroup::__construct()

public function __construct(string $name)

ShareGroup::getId()

public function getId(): ?int

ShareGroup::getName()

public function getName(): string

ShareGroup::setName()

public function setName(string $name): self

ShareGroup::getMembers()

public function getMembers(): Collection

ShareGroup::addMember()

public function addMember(User $user): self

ShareGroup::removeMember()

public function removeMember(User $user): self

ShareGroup::hasMember()

public function hasMember(User $user): bool

ShareGroup::__toString()

public function __toString(): string

ShareTask class

class ShareTask ShareTask.php:12

A task of a workspace of the drive (SharedPath::$tasks): a few words, done or not - and when, and who wrote it.

ShareTask::__construct()

public function __construct(string $title = '', ?User $author = null)

ShareTask::getId()

public function getId(): ?int

ShareTask::getWorkspace()

public function getWorkspace(): ?SharedPath

ShareTask::setWorkspace()

public function setWorkspace(?SharedPath $workspace): self

ShareTask::getTitle()

public function getTitle(): string

ShareTask::isDone()

public function isDone(): bool

ShareTask::getPosition()

public function getPosition(): int

ShareTask::setPosition()

public function setPosition(int $position): self

ShareTask::getAuthor()

public function getAuthor(): ?User

ShareTask::getCreatedAt()

public function getCreatedAt(): \DateTimeImmutable

ShareTask::getDoneAt()

public function getDoneAt(): ?\DateTimeImmutable

ShareTask::toggle()

public function toggle(): self

Done, or back to do.

SharedPath class

class SharedPath SharedPath.php:22

What the team says of a folder or a file of the drive (Base\Drive\Share\FileShare): who it is for (an audience's key: Base\Drive\Audience), a few words shown above its list, its tags (what is under it has them too), whether it is listed. A folder may be a workspace: its people (members: they see it whoever else it is for, and what is "for its members" is for them) and its tasks. The files themselves are on the storage; a path without a row here is as its nearest parent with one - the root as drive.default_audience says.

Its table keeps the name the sites created it under (sharedPath, sharedPathMember): no data moves. Its people are accounts of the application's App\Entity\User, as the core's own entities.

SharedPath::__construct()

public function __construct(string $path = '', string $audience = 'staff')

SharedPath::getId()

public function getId(): ?int

SharedPath::getPath()

public function getPath(): string

SharedPath::setPath()

public function setPath(string $path): self

SharedPath::getAudience()

public function getAudience(): string

SharedPath::setAudience()

public function setAudience(string $audience): self

SharedPath::getDescription()

public function getDescription(): ?string

SharedPath::setDescription()

public function setDescription(?string $description): self

SharedPath::getTags()

public function getTags(): array

SharedPath::setTags()

public function setTags(iterable $tags): self
$tags

each trimmed, the same one once (whatever its case)

SharedPath::isListed()

public function isListed(): ?bool

SharedPath::setListed()

public function setListed(?bool $listed): self

SharedPath::isWorkspace()

public function isWorkspace(): bool

SharedPath::setWorkspace()

public function setWorkspace(bool $workspace): self

SharedPath::allowsDeposit()

public function allowsDeposit(): bool

SharedPath::setDeposit()

public function setDeposit(bool $deposit): self

SharedPath::getMembers()

public function getMembers(): Collection

SharedPath::addMember()

public function addMember(User $user): self

SharedPath::removeMember()

public function removeMember(User $user): self

SharedPath::hasMember()

public function hasMember(User $user): bool

One of its people: by name, or through a group it is shared with.

SharedPath::getGroups()

public function getGroups(): Collection

SharedPath::addGroup()

public function addGroup(ShareGroup $group): self

SharedPath::removeGroup()

public function removeGroup(ShareGroup $group): self

SharedPath::getTasks()

public function getTasks(): Collection

SharedPath::addTask()

public function addTask(ShareTask $task): self

SharedPath::removeTask()

public function removeTask(ShareTask $task): self

Base\Drive\People

AccountPeople class

final class AccountPeople implements PeopleInterface AccountPeople.php:12

The drive's people by default: every account of drive.user_class, by its identifier and its e-mail, in one group ("accounts").

AccountPeople::__construct()

public function __construct(readonly EntityManagerInterface $entityManager, readonly string $userClass = 'App\Entity\User')

AccountPeople::grouped()

public function grouped(): array

AccountPeople::names()

public function names(): array

PeopleInterface interface

interface PeopleInterface PeopleInterface.php:12

Whom a folder of the drive may be shared with, by name and what they are to the site: groups of accounts (user id => label). The bundle's AccountPeople lists every account; a site says who its people are with its own implementation and #[AsAlias(PeopleInterface::class)] - omnibase/estate's tenants, associates, contractors and team for a property company. Each group's name is a translation key of the messages domain: share.people_group.<group>.

PeopleInterface::grouped()

public function grouped(): array
Returns

each group's people, user id => name and what they are; empty groups left out

PeopleInterface::names()

public function names(): array
Returns

user id => their name and what they are, every group together

Base\Drive\Repository

RetentionEventRepository class

class RetentionEventRepository extends ServiceEntityRepository RetentionEventRepository.php:10

RetentionEventRepository::__construct()

public function __construct(ManagerRegistry $registry)

RetentionEventRepository::log()

public function log(): array
Returns

the whole log, oldest first: a few lines a year

ShareDownloadRepository class

class ShareDownloadRepository extends ServiceEntityRepository ShareDownloadRepository.php:10

ShareDownloadRepository::__construct()

public function __construct(ManagerRegistry $registry)

ShareDownloadRepository::increment()

public function increment(string $path): void

One more download of a path: in one statement, whatever else is counting at the same time.

ShareDownloadRepository::counts()

public function counts(): array
Returns

every path's downloads

ShareDownloadRepository::deleteUnder()

public function deleteUnder(string $path): void

The counts of a path and of everything under it: gone with it.

SharedPathRepository class

class SharedPathRepository extends ServiceEntityRepository SharedPathRepository.php:10

SharedPathRepository::__construct()

public function __construct(ManagerRegistry $registry)

SharedPathRepository::byPath()

public function byPath(): array
Returns

every path the team said something of, by path

SharedPathRepository::findUnder()

public function findUnder(string $path): array

The rows of a path and of everything under it: renamed or deleted with it.

Base\Drive\Security\Voter

ShareVoter class

final class ShareVoter extends Voter ShareVoter.php:30

Who sees a path of the drive (SHARE_VIEW, the path as subject), who manages it (SHARE_MANAGE: the staff, drive.staff_role), and who works in a workspace - its tasks, the files its people bring (SHARE_WORK, the path as subject: its members and the staff). A path is for its audience (FileShare::audience, answered by Base\Drive\Audience\Audiences: the readers, the signed-in users, the members of its workspace, the staff only, and the site's own); and, whatever its audience, for the people it was shared with (FileShare::isSharedWith: a workspace's people, in it or above it).

The retention lock (drive.retention, Share\Retention): SHARE_ALTER - delete, overwrite, rename or move a path - is the staff's, and nobody's in a locked folder, the team included; SHARE_RETAIN - lift a folder's lock or put it back - is the superadmin's alone (drive.retention_role), with retention on.

const VIEW = 'SHARE_VIEW'
const MANAGE = 'SHARE_MANAGE'
const WORK = 'SHARE_WORK'
const ALTER = 'SHARE_ALTER'
const RETAIN = 'SHARE_RETAIN'

ShareVoter::__construct()

public function __construct(readonly FileShare $share, readonly Audiences $audiences, readonly Security $security, readonly string $staffRole = 'ROLE_STAFF', readonly ?Retention $retention = null)

Base\Drive\Share

FileShare class

class FileShare FileShare.php:39

The drive (« le Partage », « Cloud » on a site's pages): files a site shares with its readers, its users, the people of its workspaces and whoever its own audiences let in - an index of files, as a web server's "Index of /", with a little more: who each folder is for, whom it is shared with by name, a few words above it, its README under it, a search through the tree, each person's own root.

The files are on a storage of their own (drive.storage, alias documents.storage: the site's Google Drive folder once connected, its flysystem storage drive.local_storage otherwise - Base\Drive\Storage\DocumentsStorage), never public: they are read through ShareController, which asks ShareVoter. What the team says of a path (Base\Drive\Entity\SharedPath: its audience, its description, its tags, whether it is listed) is in the database; a path without a row is as its nearest parent with one - the root as drive.default_audience says; its tags are its own and all its folders'.

Paths are relative to the drive's root, "/"-separated, without slashes at their ends ("" is the root). Names beginning with a dot (.git, .htaccess) are never listed nor served.

With the retention lock on (drive.retention, Base\Drive\Share\Retention), what a locked folder holds is neither deleted, overwritten, renamed nor moved here (LockedException), whoever asks: the page, the commands and the bundles writing into the drive all come through these methods.

const READMES = ['README.md', 'README.txt', 'README', 'LISEZMOI.md', 'LISEZMOI.txt', 'LISEZMOI']

A folder's own words, shown under its list: the first of these found in it.

const ZIP_MAX = 1024 * 1024 * 1024

A folder larger than this is not offered as one zip: its files, one by one.

FileShare::__construct()

public function __construct(readonly FilesystemOperator $storage, readonly SharedPathRepository $paths, readonly EntityManagerInterface $entityManager, readonly ShareDownloadRepository $downloads, readonly string $defaultAudience = 'staff', readonly ?PersonalTags $personal = null, readonly ?Retention $retention = null)

FileShare::normalize()

public static function normalize(string $path): string

A path as the drive keeps it: no slashes at its ends, no "." or ".." nor hidden part.

Throws

InvalidArgumentException when it could lead out of the drive, or names something hidden

FileShare::name()

public static function name(string $name): string

A name fit for the drive, from what was typed or uploaded: its last part, without what a path cannot hold.

FileShare::slug()

public static function slug(string $path): string

A path as an address reads it (drive.slugs): each part in plain lower-case words joined by hyphens, a file keeping its extension - "Assemblées générales/2026/Procès-verbal.pdf" is "assemblees-generales/2026/proces-verbal.pdf". A part with nothing to slug stays as it is.

FileShare::resolve()

public function resolve(string $path): ?string

The path an address leads to: each part the item of that name, or else the first of its folder whose slug it is - so that an address by names, as before, and one by slugs both lead there. Null when nothing does.

FileShare::isDirectory()

public function isDirectory(string $path): bool

FileShare::isFile()

public function isFile(string $path): bool

FileShare::entries()

public function entries(string $path): array

What a folder holds, folders first, each by name.

public function search(string $query, callable $allowed, int $limit = 80, ?callable $tagsOf = null): array

What may be found under the root by its name or its tags (accents and case aside), through the whole tree: only what $allowed lets through - what someone sees, and nothing above or beside it. Folders first, then files, each by path; at most $limit.

$tagsOf

the tags it is found by, when not its own and its folders' (the ones its reader sees)

Returns

as entries(), each with its folder ("in")

FileShare::tops()

public function tops(callable $allowed): array

The highest folders someone sees when the root is not for them: each folder $allowed lets through whose own folder it does not - a tenant's, an owner's, a partner's space -, as entries of a root of their own.

FileShare::readme()

public function readme(string $path): ?array
Returns

a folder's README, as text

FileShare::audience()

public function audience(string $path): string

Who a path is for, an audience's key: its own, or its nearest parent's - drive.default_audience when none says.

FileShare::tags()

public function tags(string $path): array
Returns

a path's tags: its own, then its folders', each once

FileShare::listed()

public function listed(string $path): bool

Listed on the root and open to search engines: as itself or its nearest folder says - not listed when none does.

FileShare::downloads()

public function downloads(string $path): int

How many times a path was downloaded: a file's, or a folder's - its zips and everything under it.

FileShare::countDownload()

public function countDownload(string $path): void

One more download of a path (a file, or a folder's zip).

FileShare::setDownloads()

public function setDownloads(string $path, int $count): void

A path's downloads set at a number - the old ones of a file restored (drive:count).

FileShare::tagKey()

public static function tagKey(string $tag): string

A tag as a filter key: "Raspberry Pi" is "raspberry-pi".

FileShare::row()

public function row(string $path): ?SharedPath

What the team said of this very path, if anything.

FileShare::describe()

public function describe(string $path, ?string $audience, ?string $description, ?iterable $tags = null, bool|string|null $listed = 'keep'): void

Its audience (a key), its description, its tags and whether it is listed; an audience of null is its parent's again.

$tags

null: the ones it has

$listed

true/false, null as its folder; 'keep': as it is

FileShare::isLocked()

public function isLocked(string $path): bool

Kept by the retention lock (drive.retention): neither deleted, overwritten, renamed nor moved.

FileShare::createDirectory()

public function createDirectory(string $path): void

FileShare::upload()

public function upload(string $directory, UploadedFile $file): string

An uploaded file into a folder, under its own name - beside the one already there, if any ("notes (2).pdf").

FileShare::copy()

public function copy(string $file, string $directory): string

A file of the drive copied into a folder, under its own name - beside one already there, never over it; its new path.

FileShare::workspace()

public function workspace(string $path): ?SharedPath

The workspace a path is in: itself, or its nearest folder made one - null when none.

FileShare::createWorkspace()

public function createWorkspace(string $name, string $audience, ?string $description = null): string

A new workspace: a folder of the drive's root, who it is for (an audience's key), a few words on it.

FileShare::isSharedWith()

public function isSharedWith(string $path, User $user): bool

A path shared with someone: they are one of the people of a workspace it is in - its own or any folder above it. They see it whoever else it is for.

FileShare::shareWith()

public function shareWith(string $path, User $user, ?bool $deposit = null): void

A folder shared with someone: they see it and what it holds, from their own access, read only unless its people may bring files ($deposit). The folder becomes a workspace (its people, its tasks) if it was not one; whoever else it was for keeps it.

FileShare::shareWithGroup()

public function shareWithGroup(string $path, ShareGroup $group, ?bool $deposit = null): void

A folder shared with a group of people (Entity\ShareGroup), as shareWith() is with one person.

FileShare::setWorkspace()

public function setWorkspace(string $path, bool $workspace): void

A folder made a workspace, or a workspace made a plain folder again (its people, groups and tasks gone).

FileShare::move()

public function move(string $from, string $toDirectory, ?string $name = null): string

A file or a folder moved into another folder (and renamed, when $name is given): what it holds, what was said of it and its downloads follow.

Returns

its new path

Throws

InvalidArgumentException into itself, or onto something already there

Throws

LockedException out of a folder the retention lock keeps

FileShare::directories()

public function directories(): array
Returns

every folder of the drive, to move something into

FileShare::write()

public function write(string $path, $stream): void

A file from a stream (drive:import, the bundles filing into the drive), its folders made on the way; what is there already is replaced - unless the retention lock keeps it.

Throws

LockedException over a file the retention lock keeps

FileShare::weight()

public function weight(string $path): int

What a folder weighs, every file under it - hidden ones left out.

FileShare::delete()

public function delete(string $path): void

A file, or a folder and all it holds - and what was said of them.

Throws

LockedException in a folder the retention lock keeps

FileShare::stream()

public function stream(string $path)

FileShare::size()

public function size(string $path): int

FileShare::modified()

public function modified(string $path): int

FileShare::zip()

public function zip(string $path, callable $allowed): string

A folder as a zip, in a temporary file the caller deletes: every file under it that $allowed lets through (the viewer's rights, folder by folder), hidden ones left out.

LockedException class

final class LockedException extends RuntimeException LockedException.php:9

What the retention lock refuses (drive.retention): deleting, overwriting, renaming or moving something in a locked folder - whoever asks, the team included.

public readonly string $path

LockedException::__construct()

public function __construct(public readonly string $path)

PersonalTags class

final class PersonalTags PersonalTags.php:17

The tags each one puts on folders for themselves (drive.personal_tags): a tenant sorting their papers, an owner theirs, nobody else seeing them. Like the team's tags, a folder's apply to what it holds (to filter by). Nothing when the option is off or nobody is signed in; their rows follow a folder moved and go with one deleted (FileShare).

PersonalTags::__construct()

public function __construct(readonly EntityManagerInterface $entityManager, readonly Security $security, readonly bool $enabled = false)

PersonalTags::enabled()

public function enabled(): bool

Whether the one signed in has tags of their own here.

PersonalTags::own()

public function own(string $path): array
Returns

a path's own tags, as typed

PersonalTags::tags()

public function tags(string $path): array
Returns

a path's tags: its own, then its folders', each once

PersonalTags::add()

public function add(string $path, iterable $names): void
$names

added to a path, each once

PersonalTags::remove()

public function remove(string $path, iterable $names): void
$names

taken off a path

PersonalTags::color()

public function color(string $tag): string

A tag's colour for the one signed in: the one they chose, otherwise one drawn from its name.

PersonalTags::choose()

public function choose(string $tag, ?string $color): void

The colour they choose for a tag (#rrggbb) on every folder they gave it, or none to give it back its own.

PersonalTags::moved()

public function moved(string $from, string $to): void

Everyone's tags under a path moved, under its new path.

PersonalTags::deleted()

public function deleted(string $path): void

Everyone's tags under a path deleted, gone with it.

Retention class

class Retention Retention.php:24

The retention lock (drive.retention, off by default): with it on, every folder of the drive and what it holds is kept - nothing deleted, overwritten, renamed nor moved, by anyone, the team included (FileShare refuses it, ShareVoter's SHARE_ALTER says no). Adding files stays open.

Only the superadmin (drive.retention_role) lifts it, folder by folder - until it is put back, or for a while (a duration, an end date) -, and puts it back; each lift and each lock is a line of the log (Entity\RetentionEvent: who, when, which folder, until when, why - a reason is required), never changed nor removed. A folder is as the nearest of itself and its folders whose latest line says something: a lock, or a lift still running; a lift whose date has passed says nothing any more - the lock is back by itself, read so when asked, with no task to run.

Retention::__construct()

public function __construct(readonly RetentionEventRepository $repository, readonly EntityManagerInterface $entityManager, readonly bool $enabled = false, readonly string $role = 'ROLE_SUPERADMIN', readonly ?ClockInterface $clock = null)

Retention::enabled()

public function enabled(): bool

Retention::role()

public function role(): string

Who lifts and puts back the lock: the superadmin's role.

Retention::isLocked()

public function isLocked(string $path): bool

Kept as it is: retention on, and no lift running for it or the folder that decides for it.

Retention::guard()

public function guard(string $path): void
Throws

LockedException when the path is kept

Retention::isLockedTree()

public function isLockedTree(string $path): bool

Kept, or holding something locked again on its own: a folder goes (deleted, moved) only with all it holds.

Retention::guardTree()

public function guardTree(string $path): void
Throws

LockedException when isLockedTree()

Retention::lift()

public function lift(string $path): ?RetentionEvent

The lift a path is open by - its own, or its nearest folder's -, null when it is locked (a lock said there, or nothing said up to the root).

Retention::liftFor()

public function liftFor(string $path, ?User $by, string $reason, ?\DateTimeImmutable $until = null): RetentionEvent

A folder's lock lifted, until it is put back ($until null) or until a moment to come.

Throws

InvalidArgumentException without retention, without a reason, or with a moment gone

Retention::lock()

public function lock(string $path, ?User $by, string $reason): RetentionEvent

A folder's lock put back - also inside a folder lifted, for it and what it holds.

Throws

InvalidArgumentException without retention, or without a reason

Retention::log()

public function log(string $path): array

What the log says of a folder, newest first: its own lines, its folders' (which decide for it) and those of the folders under it - the root's is the whole log.

Retention::now()

public function now(): \DateTimeImmutable

Now, by the application's clock when it has one (a test's, frozen).

TagColors class

final class TagColors TagColors.php:12

A tag's colour, the same wherever the tag is shown: the one the team chose for it (kept in the site's settings, app.drive.tag_colors, by the tag's key), otherwise one of a few drawn from its name - so that a tag has a colour of its own before anyone chooses.

const PALETTE = ['#2a63b3', '#2f8a5b', '#c8312b', '#b7791f', '#7b4bb0', '#0f7c80', '#c2417a', '#5b6672']

TagColors::__construct()

public function __construct(readonly SettingBagInterface $settings)

TagColors::of()

public function of(string $tag): string

TagColors::drawn()

public static function drawn(string $tag): string

The colour a tag has before anyone chooses: one of the palette, drawn from its name.

TagColors::choose()

public function choose(string $tag, ?string $color): void

The colour chosen for a tag (#rrggbb), or none to give it back its own.

Base\Drive\Space

SpaceProviderInterface interface

interface SpaceProviderInterface SpaceProviderInterface.php:18

Where a person's space is in the drive: the folder their role gives them - a tenant's, an owner's, a partner's. A bundle that knows its people implements it (omnibase/estate: Locataires/<tenant>, Propriétaires/<owner>, Indivisions/<ownership>), tagged drive.space by autoconfiguration; the providers are asked in their priority's order, the first to answer wins, and nobody answering leaves the drive's own place (Spaces: drive.spaces_root/<name>).

A provider makes the folder when it is missing and shares it with the person, read only, as its business does (the drive checks it is shared once more, whatever the provider did).

const TAG = 'drive.space'

SpaceProviderInterface::spaceOf()

public function spaceOf(User $user): ?string

The person's space, made if missing, reused otherwise: its path from the drive's root - null when they are none of this provider's people.

Spaces class

class Spaces Spaces.php:22

Each person's space in the drive, and files shared on upload with named people: a file added goes, besides the folder it was added to, into the space of each person named - and of each person of a group named (Entity\ShareGroup) -, the space made if missing, reused otherwise, shared with them read only unless the uploader lets them bring files too.

Where a space is: the first provider to answer (SpaceProviderInterface, tagged drive.space - omnibase/estate's tenants, owners and partners), otherwise drive.spaces_root/<their name>, the team's (the staff audience) and theirs alone.

Spaces::__construct()

public function __construct(readonly FileShare $share, readonly iterable $providers = [], readonly string $root = 'Spaces')

Spaces::of()

public function of(User $user, bool $deposit = false): string

A person's space: made if missing, reused otherwise, shared with them (read only, unless $deposit); its path.

Spaces::deliver()

public function deliver(string $file, iterable $recipients, bool $deposit = false): array

A file of the drive shared with people: a copy in each one's space (a group: each of its people's), beside what is there, never over it - none where the file already is in their space. Each person once, however often named.

Returns

each copy's path => the space it went to

Base\Drive\Storage

DocumentsStorage class

class DocumentsStorage DocumentsStorage.php:17

Where the drive's files are (the service drive.storage, alias documents.storage, read by Base\Drive\Share\FileShare): the site's Google Drive folder once connected from the back office (google/apiclient and masbug/flysystem-google-drive-ext installed), the site's own storage otherwise (drive.local_storage, local.share by default) - and always in the tests.

DocumentsStorage::__construct()

public function __construct(readonly DriveSettings $settings, readonly DriveClient $client, readonly FilesystemOperator $local, readonly string $environment, readonly ?LoggerInterface $logger = null)

DocumentsStorage::create()

public function create(): FilesystemOperator

DocumentsStorage::isDrive()

public function isDrive(): bool

DriveClient class

class DriveClient DriveClient.php:17

Google, for the documents: the consent screen (offline access, the whole Drive - so files dropped into the folder from Drive itself show up), and a Drive service on the stored refresh token. The OAuth client is the site's (GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET); its consent screen must be published, or Google drops the token after seven days.

DriveClient::__construct()

public function __construct(readonly DriveSettings $settings, readonly UrlGeneratorInterface $urls, readonly ?string $clientId = null, readonly ?string $clientSecret = null)

DriveClient::isConfigured()

public function isConfigured(): bool

DriveClient::client()

public function client(): Client

DriveClient::authorizationUrl()

public function authorizationUrl(string $state): string

DriveClient::exchange()

public function exchange(string $code): array

DriveClient::drive()

public function drive(): Drive

DriveSettings class

class DriveSettings DriveSettings.php:15

What the site keeps of its Google Drive: the refresh token (encrypted with the app secret: it opens the whole Drive), the folder the documents live in, and who connected it. In omnibase's settings, under the names the sites stored them with (app.drive.*), sealed with the same key: a Drive connected before the bundle stays connected.

DriveSettings::__construct()

public function __construct(readonly SettingBagInterface $settings, readonly string $secret)

DriveSettings::isConnected()

public function isConnected(): bool

DriveSettings::refreshToken()

public function refreshToken(): ?string

DriveSettings::connect()

public function connect(string $refreshToken, ?string $account): void

DriveSettings::disconnect()

public function disconnect(): void

DriveSettings::folderId()

public function folderId(): ?string

DriveSettings::folderName()

public function folderName(): ?string

DriveSettings::account()

public function account(): ?string

DriveSettings::sharedDriveId()

public function sharedDriveId(): ?string

DriveSettings::useFolder()

public function useFolder(string $id, string $name, ?string $sharedDriveId = null): void

Base\Drive\Tree

DocumentsTree class

class DocumentsTree DocumentsTree.php:12

A site's layout of folders (TreeInterface) created where the files are (its storage or its Google Drive): each folder missing made, who each is for set at the same time. Folders already there are left as they are, and so is what they hold.

DocumentsTree::__construct()

public function __construct(readonly FileShare $share)

DocumentsTree::create()

public function create(TreeInterface $tree): int
Returns

the folders created

TreeInterface interface

interface TreeInterface TreeInterface.php:12

A site's own layout of folders, laid out where the files are (its storage or its Google Drive) by DocumentsTree - from the back office's Google Drive page (« Créer les dossiers ») or the site's fixtures. A property company's: its statutes, general meetings, accounts, a folder per home. The page offers it only when the site has one: a service implementing this interface, aliased with #[AsAlias(TreeInterface::class)].

TreeInterface::folders()

public function folders(): array
Returns

each folder's path (parents before their children; "" is the root) => the key of the audience it is for, or null: as its folder

TreeInterface::summary()

public function summary(): string

What it lays out, in a sentence for the back office.

Base\Drive\Twig

DriveExtension class

final class DriveExtension extends AbstractExtension DriveExtension.php:19

For a site's templates: drive_tag_color(tag), a team's tag's colour (Share\TagColors); drive_my_tag_color(tag), the colour of a tag of one's own (Share\PersonalTags); path|drive_slug, a path as the drive's addresses read it (drive.slugs: its slugs, otherwise itself) - for path('app_share', {path: entry.path|drive_slug}).

DriveExtension::__construct()

public function __construct(readonly TagColors $colors, readonly PersonalTags $personal, readonly bool $slugs = false)

DriveExtension::getFilters()

public function getFilters(): array

DriveExtension::getFunctions()

public function getFunctions(): array