:notify-due` (Deck's * ConfigService::SETTING_BOARD_NOTIFICATION_DUE_*), inlined so a renamed * constant cannot fatal this app. It is the board's "Notifications" menu * in Deck — the due-date reminder setting, which is exactly what fits a * card being moved because it fell due. */ public const DECK_OFF = 'off'; public const DECK_ASSIGNED = 'assigned'; public const DECK_ALL = 'all'; /** What Deck assumes for a user who never touched the setting. */ public const DECK_DEFAULT = self::DECK_ASSIGNED; public static function isValidMode(string $mode): bool { return in_array($mode, self::MODES, true); } /** * Mirrors Deck's own decision in NotificationHelper::sendCardDuedate(): * * - `off` never notifies — not even the owner of an unshared board; * - `all` always notifies; * - the owner of an unshared board is notified for every card, since on a * board nobody else can see "assigned" would otherwise mean nothing; * - `assigned` notifies users assigned to the card, directly or through a * group or circle. * * An unknown value is treated as Deck's default. Deck rejects anything * else when storing the setting, so that only happens if the preference * was edited by hand. * * @param bool|callable(): bool $isAssigned a callable is only invoked when * the answer actually depends on it — it costs a query per user */ public static function shouldNotify(string $deckSetting, bool $isOwnerOfUnsharedBoard, bool|callable $isAssigned): bool { if (!in_array($deckSetting, [self::DECK_OFF, self::DECK_ASSIGNED, self::DECK_ALL], true)) { $deckSetting = self::DECK_DEFAULT; } if ($deckSetting === self::DECK_OFF) { return false; } if ($deckSetting === self::DECK_ALL || $isOwnerOfUnsharedBoard) { return true; } return is_callable($isAssigned) ? (bool)$isAssigned() : $isAssigned; } }