- Application Overview
- Architecture Overview
- Design Patterns Used
- Database Schema
- Key Features & Workflows
- Strengths of Current Implementation
- Pagination Implementation
- Alert System Architecture
Breeze is a social networking modification (mod) for Simple Machines Forum (SMF) that adds Facebook-like wall functionality to user profiles. It enables users to:
- Post status updates on their own or other users' walls
- Comment on status updates
- Like statuses and comments
- Receive notifications for interactions
- View a general activity feed from buddies
- Customize individual user settings
- Backend: PHP 8.3+ with SMF 2.1.x integration
- Frontend: React 19.1.0 (TypeScript)
- Build Tools: Vite, Vitest, Biome
- Database: MySQL (via SMF's database layer)
- Dependencies: League Container (DI), League Event (Event System)
The backend follows a layered architecture with clear separation of concerns:
- Entry Point Layer -
Breeze.phpmain class - Controller Layer - Handles HTTP requests
- Service Layer - Business logic
- Repository Layer - Data access
- Entity Layer - Data models
- Validation Layer - Input validation
- Event Layer - Event-driven notifications
- Uses SMF's hook system for integration
- Registers actions, menu items, permissions, and alerts
- No file modifications required (theme-agnostic)
The frontend is a Single Page Application (SPA) built with React:
- Wall Component - Main container managing status list
- Status Component - Individual status display with comments
- Comment Component - Comment display and management
- Editor Component - Content creation (status/comments)
- Tabs Component - Tab navigation for profile sections
- Like Component - Like functionality display
- Uses React hooks (
useState,useCallback,useEffect) - Context API for permissions
- Local component state for UI state
- Implementation: League Container
- Location:
Sources/Breeze/Config/DependenciesServiceProvider.php - Purpose: Manages object creation and dependencies
- Example:
protected const array DEPENDENCIES = [
// Shared service (Singleton)
DatabaseClient::class => ['arguments' => [], 'shared' => true],
// Controller with dependencies
StatusController::class => ['arguments' => [
StatusService::class,
ValidateStatus::class,
Response::class,
]],
];- Purpose: Abstracts data access logic
- Implementation:
BaseRepositorywith specific implementations - Benefits: Testability, separation of concerns
- Key Classes:
StatusRepositoryCommentRepositoryLikeRepositoryAlertRepository
- Purpose: Encapsulates business logic
- Implementation: Service classes between controllers and repositories
- Key Classes:
StatusServiceCommentServiceAlertServicePermissionsService
- Purpose: Represents database tables as objects
- Implementation: Entity classes with type casting and serialization
- Features:
- Type casting via
castValue() - JSON serialization
- Factory method
from()
- Type casting via
- Implementation: League Event library
- Purpose: Decoupled notification system
- Events:
StatusCreatedEventStatusDeletedEventCommentCreatedEventCommentDeletedEventLikeCreatedEvent
- Implementation: Validators with different strategies
- Location:
Validate/directory - Purpose: Different validation strategies for different actions
- Traits Used:
RequestTrait- HTTP request handlingTextTrait- Text/translation handlingPermissionsTrait- Permission checkingCacheTrait- Caching operationsPersistenceTrait- Global state access
- Implementation: Entity creation via
from()static methods - Purpose: Consistent object creation
- React components composed hierarchically
- Props drilling for data flow
- Wall component acts as container
- Status/Comment components are presentational
- Uses React hooks for state and side effects
PermissionsContextfor global permissions state
id(PK, auto-increment)wall_id(user profile ID where status is posted)user_id(poster ID)body(status content - text)likes(like count - integer)created_at(timestamp - varchar)
id(PK, auto-increment)status_id(FK to breeze_status)user_id(commenter ID)body(comment content - text)likes(like count - integer)created_at(timestamp - varchar)
member_id(PK)variable(PK - setting name)value(user setting value - text)
- Used for tracking likes on statuses/comments
id_member(user who liked)content_type(status or comment)content_id(ID of liked content)like_time(timestamp)
- User types in Editor component
- React calls
postStatus()API StatusControllerreceives requestValidateStatusvalidates inputStatusServicehandles business logicStatusRepositoryinserts to database- Event dispatched (
StatusCreatedEvent) AlertServicecreates notifications- Response returned to React
- UI updates with new status
- Similar flow to status posting
- Comments attached to specific status via
statusId - Nested display in Status component
- Supports likes on comments
- Toggle-based (like/unlike)
- Tracks who liked what content
- Displays like count and user list
- Uses enum for type safety (
LikesEnum::Status,LikesEnum::Comments) - Integrated with SMF's user_likes table
- Event-driven via
EventServiceProvider AlertServicecreates notifications- Integrated with SMF's alert system
- Notifies:
- Wall owner when someone posts
- Status owner when someone comments
- Comment/Status owner when someone likes
- Granular permissions per action
- Checked at multiple layers (Controller, Service, Repository)
- Permissions context passed to React frontend
- User-specific settings override global settings
✅ Clean Architecture - Well-separated layers with clear responsibilities ✅ SOLID Principles - Good adherence to SOLID design principles ✅ Dependency Injection - Proper DI container usage with League Container ✅ Event-Driven - Decoupled notification system using events
✅ Modern PHP - PHP 8.3 with strict types and modern features ✅ Type Safety - TypeScript on frontend, typed PHP on backend ✅ Testing - Has test infrastructure (PHPUnit + Vitest) ✅ Code Standards - Uses Rector, PHPStan, Biome for code quality
✅ Modern Frontend - React 19 with hooks and functional components ✅ Build Tools - Vite for fast builds and HMR ✅ TypeScript - Type-safe frontend code
✅ No File Edits - Clean SMF integration via hooks ✅ Theme Agnostic - Works with all SMF themes ✅ Modular - Easy to extend and maintain
✅ Repository Pattern - Clean data access layer ✅ Service Layer - Business logic separation ✅ Entity Pattern - Type-safe data models ✅ Strategy Pattern - Flexible validation ✅ Factory Pattern - Consistent object creation
The Breeze application uses cursor-based pagination for improved performance and scalability. This was implemented to address the limitations of traditional offset-based pagination, especially for large datasets.
The application uses cursor-based pagination with composite cursors (id + created_at) for stable, performant pagination:
// Sources/Breeze/Repository/StatusRepository.php
$request = $this->dbClient->query(
'
SELECT {raw:columns}
FROM {db_prefix}{raw:from}
WHERE {raw:columnName} IN ({array_int:ids})
AND (
parent.created_at < {int:cursor_created_at}
OR (parent.created_at = {int:cursor_created_at} AND parent.id < {int:cursor_id})
)
ORDER BY parent.created_at DESC, parent.id DESC
LIMIT {int:limit}',
$queryParams
);Benefits of cursor-based pagination:
- Consistent performance regardless of dataset position
- No skipped or duplicate items during concurrent updates
- Scales efficiently with large datasets
- Works well with proper database indexes
- Composite Cursors: Uses both
idandcreated_atfor stable ordering - Efficient Queries: Scans only required rows with proper indexes
- Cache-Friendly: Cursor-based cache keys for better hit rates
- Backward Compatible: Gracefully handles null cursors for initial page
Quick Example:
// Get first page
$statuses = $statusRepository->getByProfile([1], 10, null);
// Generate cursor for next page
$nextCursor = $statusRepository->getNextCursor($statuses);
// Get next page
if ($nextCursor !== null) {
$moreStatuses = $statusRepository->getByProfile([1], 10, $nextCursor);
}Breeze alert system is built on SMF's native alert infrastructure and uses an event-driven architecture for decoupled notification handling.
-
Status Created (
Breeze_status_owner)- Recipient: Wall owner
- Trigger: Someone posts a status on their wall
- Handler:
StatusCreatedHandler
-
Comment Created (
Breeze_comment_status_owner,Breeze_comment_profile_owner)- Recipients: Status owner AND/OR wall owner (with duplicate prevention)
- Trigger: Someone comments on a status
- Handler:
CommentCreatedHandler
-
Like Created (
Breeze_like_status,Breeze_like_comment)- Recipient: Content owner (status or comment)
- Trigger: Someone likes content
- Handler:
LikeCreatedHandler
User Action → Event Dispatched → Event Listener → AlertService::send()
→ Handler Registered → SMF Alert System → User Notification
- Location:
Sources/Breeze/Service/AlertService.php - Purpose: Manages alert creation and handling
- Key Methods:
send(AlertEntity)- Creates and sends alertshandle(array &$alerts)- Processes alerts for display
- StatusEventListener - Handles status-related events
- CommentEventListener - Handles comment-related events
- LikeEventListener - Handles like-related events
- Location:
Sources/Breeze/Event/*/ - Purpose: Format alert text and links for display
- Registration:
HandlerServiceProvider
AlertEntity::from([
AlertEntity::ID_MEMBER => $recipientId,
AlertEntity::ID_MEMBER_STARTED => $actorId,
AlertEntity::CONTENT_TYPE => 'Breeze_status_owner',
AlertEntity::CONTENT_ID => $statusId,
AlertEntity::CONTENT_ACTION => 'created',
]);- Uses SMF's
user_alertstable - Integrates with SMF's alert preferences system
- Supports email notifications via SMF
- Respects user notification settings
Document Version: 2.0 Last Updated: 2026-02-25 Status: Current Architecture Documentation