Lue dans les fichiers PHP du paquet au commit 796be79ff0db : 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é.
DemoControllerclassThe demonstrator: it seeds two members and a conversation between them, signs you in as one, walks the mailbox's rules - then hands over to the mailbox itself. "Switch member" swaps you to the other side of the conversation, so both ends of an exchange can be seen in one browser.
3 methods
UserclassThe demo's member. base-bundle's User identifies people by email and has no username; the forum and the mailbox address members by username (an @mention, a recipient typed by hand), so the application's User carries one - as every base-bundle application's User does.
3 methods
UserRepositoryclass
MailboxBundleclassPrivate messages between members: conversations, each with its participants and their own read/archive state.
3 methods
Base\Mailbox\Attachment\Office
ConversationAudienceclassWho reads a conversation's attachments in the vault: whoever takes part in the conversation, and the staff of the desk it was written to. Nobody withdraws one from here.
2 methods
VaultAttachmentsclassA message's attachment kept in omnibase/office's encrypted vault (when mailbox.attachments is on and omnibase/office installed): the file is a Document of the conversation ("mailbox:<id>"), read by its participants through ConversationAudience and logged like any other. The vault does not e-mail about it: the message's own notice does.
4 methods · 1 constant
Base\Mailbox\Controller\Client
MailboxControllerclassThe member's mailbox: inbox, archives, a conversation, composing and replying. Everything is behind ROLE_USER (mailbox.required_role is checked on top in each action).
8 methods
MessageCipherclassSubjects and messages encrypted at rest, when mailbox.encrypt is on: libsodium's secretbox, "mbx1:" + base64(nonce + box) in the same columns.
6 methods · 1 constant
Base\Mailbox\DependencyInjection
MailboxConfigurationclass1 method
MailboxExtensionclass3 methods
DesksclassThe desks (mailbox.desks): "the secretariat", "the front office". A member writes to one without knowing who is behind it; whoever holds its role - their own, a group's, or through the role hierarchy - reads its conversations and answers them.
10 methods
ConversationclassA conversation: a subject, its participants, its messages. Replies stay in the conversation rather than starting a new one - what the old inbox did with "rep_s"/"rep_eid" by hand.
18 methods
MessageclassOne message of a conversation. Plain text; line breaks are kept, nothing else is interpreted.
10 methods
ParticipantclassOne member's view of a conversation: when they last read it, whether they archived or deleted it. The conversation itself is shared; this row is theirs - so one member deleting a conversation never removes it from the other's box.
18 methods
MessageSentEventclassA message was sent - a new conversation's first, or a reply. $desk: the desk it was written to, if any.
1 method · 5 properties
AttachmentclassA file sent with a message: only where it is kept - the id of its document in omnibase/office's encrypted vault - and whether it is a picture to show in the conversation. Its name and content are the vault's.
5 methods
DeskConversationclassA conversation written to a desk rather than to someone: its author is its only participant at first; whoever holds the desk's role reads it, and joins it by answering. In a table of its own so that a site without desks has nothing to migrate.
6 methods
Base\Mailbox\Extension\Repository
AttachmentRepositoryclass2 methods
DeskConversationRepositoryclass5 methods
ComposeModelclassThe compose form: recipients as typed usernames, a subject, the first message.
1 method · 4 properties
ComposeTypeclass2 methods
ReplyTypeclassA reply inside a conversation: the text only.
2 methods
NotifyListenerclass"A message awaits you", when mailbox.notify is on: each other participant who kept the conversation is mailed a link to it - not its content, not its subject, not who wrote. The desk's staff are not mailed: they see what waits in their box.
2 methods
DirectoryclassWhom a member may write to when mailbox.directory is on: the desks, then the people the site's RecipientProviderInterface services offer. Choices are "desk:<name>" and "user:<id>"; what comes back from the form is looked up here again, never trusted.
3 methods
RecipientProviderInterfaceinterfaceWhom a member may write to by name rather than by username, when mailbox.directory is on: a site's own rule - a patient's practitioners, a tenant's manager. Autoconfigured (tag mailbox.recipient_provider).
1 method
ConversationRepositoryclass4 methods · 3 constants
MessageRepositoryclass1 method
ParticipantRepositoryclass
MailboxclassThe rules of the mailbox, in one place: who may write to whom, how often, how long a subject may be, how full a box may get. The controller only turns a refusal into a flash.
13 methods
MailboxExceptionclassA refusal the member should read: the message is a translation key in the "mailbox" domain.
2 methods
MailboxTwigExtensionclassmailbox_unread_count() unread conversations of the signed-in member, for a badge in the site's menu. Counted once per request; null when nobody is signed in or the count cannot be had - a menu must never 500.
8 methods
App\Controller
DemoController class
class DemoController extends AbstractController DemoController.php:24
The demonstrator: it seeds two members and a conversation between them, signs you in as one, walks the mailbox's rules - then hands over to the mailbox itself. "Switch member" swaps you to the other side of the conversation, so both ends of an exchange can be seen in one browser.
Demo scaffolding throughout: a real application signs members in through base-bundle's security controllers.
DemoController::__construct()
public function __construct(readonly EntityManagerInterface $entityManager, readonly Mailbox $mailbox, readonly Security $security)DemoController::index()
public function index(): ResponseDemoController::switch()
public function switch(): ResponseSwap to the other member, to read the conversation from the other side.
App\Entity
User class
class User extends User User.php:15
The demo's member. base-bundle's User identifies people by email and has no username; the forum and the mailbox address members by username (an @mention, a recipient typed by hand), so the application's User carries one - as every base-bundle application's User does.
User::getUsername()
public function getUsername(): ?stringUser::setUsername()
public function setUsername(string $username): selfUser::__toString()
public function __toString(): stringApp\Repository
UserRepository class
class UserRepository extends UserRepository UserRepository.php:5
Base\Mailbox
MailboxBundle class
class MailboxBundle extends AbstractBaseBundle MailboxBundle.php:18
Private messages between members: conversations, each with its participants and their own read/archive state.
Deliberately NOT built on Thread: a private message is not content that is published, tagged, liked or listed - it is mail. What it shares with the rest of base-bundle is the User, the Timestamp attributes and the paginator.
MailboxBundle::__construct()
public function __construct()MailboxBundle::getPath()
public function getPath(): stringModern layout: package root, templates/ as @Mailbox, entities in src/Entity.
MailboxBundle::build()
public function build(ContainerBuilder $container): voidBase\Mailbox\Attachment\Office
ConversationAudience class
final class ConversationAudience implements AudienceResolverInterface ConversationAudience.php:18
Who reads a conversation's attachments in the vault: whoever takes part in the conversation, and the staff of the desk it was written to. Nobody withdraws one from here.
ConversationAudience::__construct()
public function __construct(readonly EntityManagerInterface $entityManager, readonly Desks $desks)ConversationAudience::decide()
public function decide(string $attribute, Document $document, UserInterface $user): ?boolVaultAttachments class
class VaultAttachments VaultAttachments.php:25
A message's attachment kept in omnibase/office's encrypted vault (when mailbox.attachments is on and omnibase/office installed): the file is a Document of the conversation ("mailbox:<id>"), read by its participants through ConversationAudience and logged like any other. The vault does not e-mail about it: the message's own notice does.
const CONTEXT = 'mailbox:'
VaultAttachments::__construct()
public function __construct(readonly DocumentVault $vault, readonly EntityManagerInterface $entityManager, readonly bool $enabled = false)VaultAttachments::isEnabled()
public function isEnabled(): boolVaultAttachments::attach()
public function attach(Message $message, UploadedFile $file, User $sender, User $owner): Attachment$ownerwhose document it is: the other participant, or the sender's own when written to a desk
- Throws
MailboxException
VaultAttachments::of()
public function of(Conversation $conversation): array- Returns
by message id
Base\Mailbox\Controller\Client
MailboxController class
class MailboxController extends AbstractController MailboxController.php:35
The member's mailbox: inbox, archives, a conversation, composing and replying. Everything is behind ROLE_USER (mailbox.required_role is checked on top in each action).
Route names are mailbox_*; the paths are French, as the site is.
MailboxController::__construct()
public function __construct(EntityManagerInterface $entityManager, readonly Mailbox $mailbox, readonly PaginatorInterface $paginator, readonly TranslatorInterface $translator, readonly int $perPage = 20, readonly string $requiredRole = 'ROLE_USER', readonly ?Desks $desks = null, readonly ?Directory $directory = null, readonly bool $useDirectory = false, readonly int $poll = 0, readonly ?object $attachments = null)MailboxController::Index()
public function Index(Request $request, string $box = ConversationRepository::BOX_INBOX): ResponseMailboxController::Compose()
public function Compose(Request $request, ?string $to = null): ResponseMailboxController::Show()
public function Show(Request $request, int $id): ResponseMailboxController::State()
public function State(int $id): JsonResponseWhat the open conversation's page asks every mailbox.poll seconds: has something arrived?
MailboxController::Reply()
public function Reply(Request $request, int $id): ResponseMailboxController::Action()
public function Action(Request $request, int $id, string $action): Responsearchive / unarchive / star / unstar / delete - one POST, one switch, CSRF in the form.
MailboxController::Batch()
public function Batch(Request $request, string $action): ResponseSeveral at once from the list: the old inbox's row of checkboxes.
Base\Mailbox\Crypto
MessageCipher class
class MessageCipher MessageCipher.php:17
Subjects and messages encrypted at rest, when mailbox.encrypt is on: libsodium's secretbox, "mbx1:" + base64(nonce + box) in the same columns.
A value without that mark is read as it is - what was written before encryption was turned on stays readable.
Fail closed: asked to encrypt without a usable key (mailbox.key, base64 of 32 bytes), it refuses - the message is not sent, never stored clear.
const PREFIX = 'mbx1:'
MessageCipher::__construct()
public function __construct(readonly bool $enabled = false, ?string $key = null)MessageCipher::isEnabled()
public function isEnabled(): boolMessageCipher::isReady()
public function isReady(): boolEncryption asked for and a key to do it with.
MessageCipher::encrypt()
public function encrypt(string $text): string- Throws
MailboxException error.no_key
MessageCipher::decrypt()
public function decrypt(?string $value): ?stringThe clear text; null when it cannot be read (no key, another key, altered).
MessageCipher::isEncrypted()
public static function isEncrypted(?string $value): boolBase\Mailbox\DependencyInjection
MailboxConfiguration class
class MailboxConfiguration extends AbstractBaseConfiguration MailboxConfiguration.php:8
MailboxConfiguration::getConfigTreeBuilder()
public function getConfigTreeBuilder(): TreeBuilderMailboxExtension class
class MailboxExtension extends AbstractBaseExtension implements PrependExtensionInterface MailboxExtension.php:12
MailboxExtension::prepend()
public function prepend(ContainerBuilder $container): voidThe extension's own tables (mailbox_desk_conversation, mailbox_attachment) are mapped only where desks or attachments are configured: a site that uses neither keeps the three tables it had, and no migration to write.
MailboxExtension::getConfiguration()
public function getConfiguration(array $config, ContainerBuilder $container): MailboxConfigurationMailboxExtension::load()
public function load(array $configs, ContainerBuilder $container): voidBase\Mailbox\Desk
Desks class
class Desks Desks.php:19
The desks (mailbox.desks): "the secretariat", "the front office". A member writes to one without knowing who is behind it; whoever holds its role - their own, a group's, or through the role hierarchy - reads its conversations and answers them.
Desks::__construct()
public function __construct(readonly EntityManagerInterface $entityManager, readonly RoleHierarchyInterface $roles, readonly array $desks = [])Desks::isEnabled()
public function isEnabled(): boolDesks::all()
public function all(): array- Returns
name => label
Desks::has()
public function has(string $desk): boolDesks::label()
public function label(string $desk): stringDesks::forUser()
public function forUser(User $user): array- Returns
the desks this user answers at
Desks::of()
public function of(Conversation $conversation): ?DeskConversationDesks::staffs()
public function staffs(User $user, Conversation $conversation): boolWhether the user reads this conversation as staff of its desk.
Desks::countWaiting()
public function countWaiting(User $user): intDesks::conversations()
public function conversations(): DeskConversationRepositoryThe repository, asked only where desks are configured: without them the entity is not mapped (MailboxExtension::prepend) and must not be touched.
Base\Mailbox\Entity
Conversation class
class Conversation Conversation.php:18
A conversation: a subject, its participants, its messages. Replies stay in the conversation rather than starting a new one - what the old inbox did with "rep_s"/"rep_eid" by hand.
Conversation::__construct()
public function __construct(?string $subject = null)Conversation::__toString()
public function __toString(): stringConversation::getId()
public function getId(): ?intConversation::getSubject()
public function getSubject(): ?stringConversation::setSubject()
public function setSubject(?string $subject): selfConversation::getParticipants()
public function getParticipants(): CollectionConversation::addParticipant()
public function addParticipant(User $user): ParticipantConversation::getParticipant()
public function getParticipant(User $user): ?ParticipantConversation::hasParticipant()
public function hasParticipant(User $user): boolConversation::getOthers()
public function getOthers(?User $except = null): array- Returns
everyone in the conversation except $except
Conversation::getMessages()
public function getMessages(): CollectionConversation::addMessage()
public function addMessage(Message $message): selfConversation::getLastMessage()
public function getLastMessage(): ?MessageConversation::getCreatedAt()
public function getCreatedAt(): ?\DateTimeInterfaceConversation::getLastMessageAt()
public function getLastMessageAt(): ?\DateTimeInterfaceConversation::getLastSender()
public function getLastSender(): ?UserConversation::getMessageCount()
public function getMessageCount(): intConversation::isUnreadFor()
public function isUnreadFor(User $user): boolUnread for this member: something arrived after they last read.
Message class
class Message Message.php:12
One message of a conversation. Plain text; line breaks are kept, nothing else is interpreted.
Message::__construct()
public function __construct(?User $sender = null, ?string $content = null)Message::__toString()
public function __toString(): stringMessage::getId()
public function getId(): ?intMessage::getConversation()
public function getConversation(): ?ConversationMessage::setConversation()
public function setConversation(?Conversation $conversation): selfMessage::getSender()
public function getSender(): ?UserMessage::setSender()
public function setSender(?User $sender): selfMessage::getContent()
public function getContent(): ?stringMessage::setContent()
public function setContent(?string $content): selfMessage::getCreatedAt()
public function getCreatedAt(): ?\DateTimeInterfaceParticipant class
class Participant Participant.php:15
One member's view of a conversation: when they last read it, whether they archived or deleted it. The conversation itself is shared; this row is theirs - so one member deleting a conversation never removes it from the other's box.
Participant::__construct()
public function __construct(?Conversation $conversation = null, ?User $user = null)Participant::getId()
public function getId(): ?intParticipant::getConversation()
public function getConversation(): ?ConversationParticipant::setConversation()
public function setConversation(?Conversation $conversation): selfParticipant::getUser()
public function getUser(): ?UserParticipant::setUser()
public function setUser(?User $user): selfParticipant::getLastReadAt()
public function getLastReadAt(): ?\DateTimeInterfaceParticipant::markRead()
public function markRead(?\DateTimeInterface $at = null): selfParticipant::isArchived()
public function isArchived(): boolParticipant::getArchivedAt()
public function getArchivedAt(): ?\DateTimeInterfaceParticipant::archive()
public function archive(): selfParticipant::unarchive()
public function unarchive(): selfParticipant::isDeleted()
public function isDeleted(): boolParticipant::getDeletedAt()
public function getDeletedAt(): ?\DateTimeInterfaceParticipant::delete()
public function delete(): selfParticipant::restore()
public function restore(): selfParticipant::isStarred()
public function isStarred(): boolParticipant::setStarred()
public function setStarred(bool $starred): selfBase\Mailbox\Event
MessageSentEvent class
final class MessageSentEvent extends Event MessageSentEvent.php:11
A message was sent - a new conversation's first, or a reply. $desk: the desk it was written to, if any.
public readonly Conversation $conversationpublic readonly Message $messagepublic readonly User $senderpublic readonly ?string $deskpublic readonly bool $first
MessageSentEvent::__construct()
public function __construct(public readonly Conversation $conversation, public readonly Message $message, public readonly User $sender, public readonly ?string $desk = null, public readonly bool $first = false)Base\Mailbox\Extension\Entity
Attachment class
class Attachment Attachment.php:14
A file sent with a message: only where it is kept - the id of its document in omnibase/office's encrypted vault - and whether it is a picture to show in the conversation. Its name and content are the vault's.
Attachment::__construct()
public function __construct(Message $message, int $documentId, bool $image = false)Attachment::getId()
public function getId(): ?intAttachment::getMessage()
public function getMessage(): MessageAttachment::getDocumentId()
public function getDocumentId(): intAttachment::isImage()
public function isImage(): boolDeskConversation class
class DeskConversation DeskConversation.php:16
A conversation written to a desk rather than to someone: its author is its only participant at first; whoever holds the desk's role reads it, and joins it by answering. In a table of its own so that a site without desks has nothing to migrate.
DeskConversation::__construct()
public function __construct(Conversation $conversation, string $desk, ?User $author)DeskConversation::getId()
public function getId(): ?intDeskConversation::getConversation()
public function getConversation(): ConversationDeskConversation::getDesk()
public function getDesk(): stringDeskConversation::getAuthor()
public function getAuthor(): ?UserDeskConversation::isWaiting()
public function isWaiting(): boolThe author wrote last: the desk has something to answer.
Base\Mailbox\Extension\Repository
AttachmentRepository class
class AttachmentRepository extends ServiceEntityRepository AttachmentRepository.php:11
AttachmentRepository::__construct()
public function __construct(ManagerRegistry $registry)AttachmentRepository::findByConversation()
public function findByConversation(Conversation $conversation): array- Returns
a conversation's attachments, by message id
DeskConversationRepository class
class DeskConversationRepository extends ServiceEntityRepository DeskConversationRepository.php:12
DeskConversationRepository::__construct()
public function __construct(ManagerRegistry $registry)DeskConversationRepository::findOneByConversation()
public function findOneByConversation(Conversation $conversation): ?DeskConversationDeskConversationRepository::createDeskQuery()
public function createDeskQuery(array $desks): Query$desksthe conversations written to those desks, the latest first
DeskConversationRepository::countWaiting()
public function countWaiting(array $desks): int$deskshow many wait for an answer: their author wrote last
DeskConversationRepository::findWaiting()
public function findWaiting(array $desks, int $limit = 5): arrayBase\Mailbox\Form\Model
ComposeModel class
class ComposeModel ComposeModel.php:8
The compose form: recipients as typed usernames, a subject, the first message.
public ?string $recipients = nullComma-separated usernames; the service resolves and checks them.
public ?string $to = nullWith mailbox.directory: a choice of the directory, "desk:<name>" or "user:<id>".
public ?string $subject = nullThe longest: the form's subject_max_length option (mailbox.subject_max_length), ComposeType's constraint.
public ?string $content = null
ComposeModel::getRecipientList()
public function getRecipientList(): arrayBase\Mailbox\Form\Type
ComposeType class
class ComposeType extends AbstractType ComposeType.php:15
ComposeType::configureOptions()
public function configureOptions(OptionsResolver $resolver): voidComposeType::buildForm()
public function buildForm(FormBuilderInterface $builder, array $options): voidReplyType class
class ReplyType extends AbstractType ReplyType.php:13
A reply inside a conversation: the text only.
ReplyType::configureOptions()
public function configureOptions(OptionsResolver $resolver): voidReplyType::buildForm()
public function buildForm(FormBuilderInterface $builder, array $options): voidBase\Mailbox\Notification
NotifyListener class
final class NotifyListener NotifyListener.php:19
"A message awaits you", when mailbox.notify is on: each other participant who kept the conversation is mailed a link to it - not its content, not its subject, not who wrote. The desk's staff are not mailed: they see what waits in their box.
NotifyListener::__construct()
public function __construct(readonly ?MailerInterface $mailer, readonly UrlGeneratorInterface $urls, readonly TranslatorInterface $translator, readonly bool $enabled = false, readonly ?string $sender = null)NotifyListener::onMessageSent()
public function onMessageSent(MessageSentEvent $event): voidBase\Mailbox\Recipient
Directory class
class Directory Directory.php:15
Whom a member may write to when mailbox.directory is on: the desks, then the people the site's RecipientProviderInterface services offer. Choices are "desk:<name>" and "user:<id>"; what comes back from the form is looked up here again, never trusted.
Directory::__construct()
public function __construct(readonly Desks $desks, iterable $providers = [])Directory::choices()
public function choices(User $sender): array- Returns
label => choice
Directory::resolve()
public function resolve(User $sender, ?string $choice): string|User|nullThe desk's name, or the user, a choice stands for; null when it was not offered to this sender.
RecipientProviderInterface interface
interface RecipientProviderInterface RecipientProviderInterface.php:13
Whom a member may write to by name rather than by username, when mailbox.directory is on: a site's own rule - a patient's practitioners, a tenant's manager. Autoconfigured (tag mailbox.recipient_provider).
RecipientProviderInterface::recipients()
public function recipients(User $sender): array- Returns
a label => the account
Base\Mailbox\Repository
ConversationRepository class
class ConversationRepository extends ServiceEntityRepository ConversationRepository.php:17
const BOX_INBOX = 'inbox'const BOX_ARCHIVE = 'archive'const BOX_SENT = 'sent'
ConversationRepository::createBoxQuery()
public function createBoxQuery(User $user, string $box = self::BOX_INBOX): QueryConversationRepository::countInbox()
public function countInbox(User $user): intHow many conversations sit in the member's inbox (the quota).
ConversationRepository::countUnread()
public function countUnread(User $user): intConversations with something the member has not read yet.
ConversationRepository::findOneForUser()
public function findOneForUser(int $id, User $user): ?ConversationA conversation the member takes part in (and has not deleted), fully loaded.
MessageRepository class
class MessageRepository extends ServiceEntityRepository MessageRepository.php:15
MessageRepository::findLastBySender()
public function findLastBySender(User $sender): ?MessageThe member's latest message, whatever the conversation - the flood check.
ParticipantRepository class
class ParticipantRepository extends ServiceEntityRepository ParticipantRepository.php:14
Base\Mailbox\Service
Mailbox class
class Mailbox Mailbox.php:27
The rules of the mailbox, in one place: who may write to whom, how often, how long a subject may be, how full a box may get. The controller only turns a refusal into a flash.
The limits are the historical site's: 100 conversations in a box, two minutes between two messages, a 55-character subject.
Mailbox::__construct()
public function __construct(readonly EntityManagerInterface $entityManager, readonly Security $security, readonly int $inboxLimit = 100, readonly int $floodInterval = 120, readonly int $subjectMaxLength = 55, readonly int $contentMaxLength = 10000, readonly int $maxRecipients = 5, readonly ?MessageCipher $cipher = null, readonly ?Desks $desks = null, readonly ?EventDispatcherInterface $dispatcher = null)Mailbox::compose()
public function compose(User $sender, array $usernames, string $subject, string $content): ConversationStart a conversation. Recipients are usernames, typed by the sender, matched case-insensitively.
- Throws
MailboxException
Mailbox::composeTo()
public function composeTo(User $sender, array $recipients, string $subject, string $content): ConversationStart a conversation with accounts already known (a directory's choice) rather than typed usernames.
- Throws
MailboxException
Mailbox::composeToDesk()
public function composeToDesk(User $sender, string $desk, string $subject, string $content): ConversationWrite to a desk (mailbox.desks): the author is the conversation's only participant until someone of the desk answers.
- Throws
MailboxException
Mailbox::reveal()
public function reveal(?string $stored): ?stringA subject or a message as written: decrypted when it was stored encrypted; null when it cannot be read.
Mailbox::reply()
public function reply(User $sender, Conversation $conversation, string $content): Message- Throws
MailboxException
Mailbox::markRead()
public function markRead(User $user, Conversation $conversation): voidMailbox::archive()
public function archive(User $user, Conversation $conversation, bool $archive = true): voidMailbox::star()
public function star(User $user, Conversation $conversation, bool $starred): voidMailbox::delete()
public function delete(User $user, Conversation $conversation): voidDelete for this member only. When nobody keeps it any more the conversation itself goes.
Mailbox::countUnread()
public function countUnread(User $user): intMailbox::getInboxLimit()
public function getInboxLimit(): intMailbox::getSubjectMaxLength()
public function getSubjectMaxLength(): intMailboxException class
class MailboxException extends RuntimeException MailboxException.php:6
A refusal the member should read: the message is a translation key in the "mailbox" domain.
MailboxException::__construct()
public function __construct(string $key, readonly array $parameters = [])MailboxException::getParameters()
public function getParameters(): arrayBase\Mailbox\Twig
MailboxTwigExtension class
final class MailboxTwigExtension extends AbstractExtension MailboxTwigExtension.php:26
mailbox_unread_count() unread conversations of the signed-in member, for a badge in the site's menu. Counted once per request; null when nobody is signed in or the count cannot be had - a menu must never 500.
|mailbox_text a message body as HTML: escaped, paragraphs and line breaks kept, URLs made clickable. |mailbox_plain a subject or a message as written (decrypted when mailbox.encrypt stored it encrypted). mailbox_desks() the desks the signed-in member answers at (name => label); mailbox_desk_waiting() how many of their conversations wait for an answer.
MailboxTwigExtension::__construct()
public function __construct(readonly Mailbox $mailbox, readonly Security $security, readonly ?Desks $desks = null)MailboxTwigExtension::getFunctions()
public function getFunctions(): arrayMailboxTwigExtension::getFilters()
public function getFilters(): arrayMailboxTwigExtension::unreadCount()
public function unreadCount(): ?intMailboxTwigExtension::desks()
public function desks(): array- Returns
the desks the signed-in member answers at
MailboxTwigExtension::deskWaiting()
public function deskWaiting(): intMailboxTwigExtension::plain()
public function plain(?string $stored): stringAs written; "…" in place of what cannot be decrypted.
MailboxTwigExtension::text()
public function text(?string $content): string