docs: map existing codebase

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-02 09:28:40 +02:00
parent 10bfe6debc
commit 63cf69f114
7 changed files with 1490 additions and 0 deletions

View File

@@ -0,0 +1,302 @@
# Architecture
**Analysis Date:** 2026-04-02
## Pattern Overview
**Overall:** Monolithic PowerShell Application with WinForms UI and Async Runspace Pattern
**Key Characteristics:**
- Single-file PowerShell script (6408 lines) serving as entry point
- Native WinForms GUI (no external UI framework dependencies)
- Asynchronous operations via dedicated PowerShell runspaces to prevent UI blocking
- Hashtable-based state management for inter-runspace communication
- PnP.PowerShell module for all SharePoint Online interactions
- Profile and template persistence via JSON files
- Region-based code organization for logical grouping
## Layers
**Presentation Layer (GUI):**
- Purpose: User interface and interaction handling
- Location: `Sharepoint_ToolBox.ps1` lines 2990-3844 (GUI setup) + event handlers
- Contains: WinForms controls, dialogs, input validation, visual updates
- Depends on: Shared helpers, Settings layer
- Used by: Event handlers, runspace callbacks via synchronized hashtable
**Application Layer (Business Logic):**
- Purpose: Core operations for each feature (permissions, storage, templates, search, duplicates)
- Location: `Sharepoint_ToolBox.ps1` multiple regions:
- Permissions: lines 1784-2001
- Storage: lines 2002-2110
- File Search: lines 2112-2233
- Duplicates: lines 2235-2408
- Templates: lines 475-1360
- Transfer/Bulk: lines 2410-3000
- Contains: PnP API calls, data aggregation, report generation
- Depends on: PnP.PowerShell module, Presentation feedback
- Used by: Event handlers via runspaces, HTML/CSV export functions
**Data Access Layer:**
- Purpose: File I/O, persistence, caching
- Location: `Sharepoint_ToolBox.ps1` dedicated regions:
- Profile Management: lines 48-127
- Settings: lines 129-154
- Template Management: lines 475-533
- Contains: JSON serialization/deserialization, profile CRUD, settings management
- Depends on: File system access
- Used by: Application layer, GUI initialization
**Export & Reporting Layer:**
- Purpose: Transform data to CSV and interactive HTML
- Location: `Sharepoint_ToolBox.ps1`:
- Permissions HTML: lines 1361-1617
- Storage HTML: lines 1619-1784
- Search HTML: lines 2112-2233
- Duplicates HTML: lines 2235-2408
- Transfer HTML: lines 2412-2547
- Contains: HTML template generation, JavaScript for interactivity, CSV formatting
- Depends on: Application layer data, System.Drawing for styling
- Used by: Feature implementations for export operations
**Integration Layer:**
- Purpose: External service communication (SharePoint, PnP.PowerShell)
- Location: `Sharepoint_ToolBox.ps1` PnP function regions
- Contains: Connect-PnPOnline, Get-PnP* cmdlets, authentication handling
- Depends on: PnP.PowerShell module, credentials from user input
- Used by: Application layer operations
**Utilities & Helpers:**
- Purpose: Cross-cutting formatting, UI helpers, internationalization
- Location: `Sharepoint_ToolBox.ps1`:
- Shared Helpers: lines 4-46
- Internationalization: lines 2732-2989
- UI Control Factories: lines 3119-3146
- Contains: Write-Log, Format-Bytes, EscHtml, T() translator, control builders
- Depends on: System.Windows.Forms, language JSON file
- Used by: All other layers
## Data Flow
**Permissions Report Generation:**
1. User selects site(s) and report options in GUI (Permissions tab)
2. Click "Générer le rapport" triggers event handler at line 4068+
3. Validation via `Validate-Inputs` (line 30)
4. GUI triggers runspace via `Start-Job` with user parameters
5. Runspace calls `Generate-PnPSitePermissionRpt` (line 1852)
6. `Generate-PnPSitePermissionRpt` connects to SharePoint via `Connect-PnPOnline` (line 1864)
7. Recursive permission scanning:
- `Get-PnPWebPermission` (line 1944) for site/webs
- `Get-PnPListPermission` (line 1912) for lists and libraries
- `Get-PnPFolderPermission` (line 1882) for folders (if enabled)
- `Get-PnPPermissions` (line 1786) extracts individual role assignments
8. Results accumulated in `$script:AllPermissions` array
9. Export based on format choice:
- CSV: `Merge-PermissionRows` (line 1363) then `Export-Csv`
- HTML: `Export-PermissionsToHTML` (line 1389) generates interactive report
10. Output file path returned to UI via synchronized hashtable
11. User can open report via `btnPermOpen` click handler
**Storage Metrics Scan:**
1. User selects storage options and sites
2. Click "Générer les métriques" triggers runspace job
3. Job calls `Get-SiteStorageMetrics` (line 2004)
4. Per-site or per-library scanning:
- Connect to web via `Connect-PnPOnline`
- `Get-PnPList` retrieves document libraries (if per-library mode)
- `Get-PnPFolderStorageMetric` for library/root metrics
- `Collect-FolderStorage` (recursive nested function) walks folder tree to configured depth
5. Results accumulate in `$script:storageResults` with hierarchy intact
6. HTML or CSV export writes report file
7. File path communicated back to UI
**Site Picker (Browse Sites):**
1. User clicks "Voir les sites" button
2. `Show-SitePicker` dialog opens (line 212)
3. User clicks "Charger les sites" button
4. Dialog initializes `$script:_pkl` state hashtable (line 315)
5. Runspace spawned in `btnLoad.Add_Click` (line 395)
6. Runspace connects to admin site and retrieves all sites via `Get-PnPTenantSite`
7. Results queued back to UI via synchronized `$script:_pkl.Sync` hashtable
8. Timer polls `$script:_pkl.Sync` and updates ListView asynchronously
9. User filters by text, sorts columns, checks/unchecks sites
10. Returns selected site URLs in `$script:SelectedSites` array
**File Search:**
1. User enters search criteria (extensions, regex, date ranges, etc.)
2. Click "Lancer la recherche" triggers runspace
3. Runspace uses PnP Search API (KQL) with filters:
- File extension filters via `fileExtension:ext1` OR syntax
- Date range filters via `Created >= date`
- Regex applied client-side after retrieval
4. Results paginated and accumulated
5. Exported to CSV or HTML with interactive filtering/sorting
**Duplicate Detection:**
1. User chooses file or folder mode and comparison criteria
2. Click "Lancer le scan" triggers runspace
3. File duplicates: Search API with filename-based grouping
4. Folder duplicates: Enumerate all folders, compare attributes (size, dates, subfolder/file counts)
5. Results grouped by match criteria
6. HTML export shows grouped duplicates with visual indicators (green/orange for matching/differing fields)
**Template Capture & Apply:**
1. Capture mode: `Show-TemplateManager` dialog (line 542)
- User selects "Capture from site"
- Runspace scans site structure via `Get-PnPList`, `Get-PnPFolderItem`, `Get-PnPWebPermission`
- Captures libraries, folders, permission groups, site logo, title
- Persisted to `Sharepoint_Templates.json`
2. Apply mode: User selects template and target site
- Runspace creates lists/libraries via `New-PnPList`
- Replicates folder structure via `New-PnPFolder`
- Applies permission groups if selected
- Logs creation results
**State Management:**
- `$script:` variables hold state across runspace calls (profiles, sites, results, settings)
- Synchronized hashtables (`$script:_pkl`, `$script:_sync`) enable runspace-to-UI communication
- Timer at line 3850-3870 polls synchronized hashtable and updates GUI with progress/results
- Event handlers trigger jobs but don't block waiting for completion (asynchronous pattern)
## Key Abstractions
**Runspace Encapsulation:**
- Purpose: Execute long-running SharePoint operations without freezing GUI
- Pattern: `$job = Start-Job -ScriptBlock { ... } -RunspacePool $rsPool`
- Example: `Start-NextStorageScan` (line 4536) manages storage scan runspace jobs
- Trade-off: Requires careful state management via shared hashtables; no direct closures
**Hashtable-Based State:**
- Purpose: Share mutable state between main runspace and job runspaces
- Pattern: `$sync = @{ Data = @(); Status = "Running" }` passed to job
- Example: `$script:_pkl` (line 315) manages site picker state across checkbox events
- Benefit: Avoids closure complexity; timer can poll changes safely
**Dialog Modal Isolation:**
- Purpose: Site picker and template manager as isolated UI contexts
- Pattern: `Show-SitePicker` and `Show-TemplateManager` create self-contained `Form` objects
- State stored in `$script:_pkl` and `$script:_tpl` respectively
- Returns result arrays (selected sites, template data) to main form
**Language Translation System:**
- Purpose: Internationalization without external dependencies
- Pattern: `T("key")` function (line 2908) looks up keys in `$script:LangDict` hashtable
- Source: `lang/fr.json` contains French translations; English is hardcoded
- Used throughout: All UI labels, buttons, messages use `T()` for localization
**HTML Export Templates:**
- Purpose: Dynamically generate interactive HTML reports with embedded JavaScript
- Pattern: String templates with `@"` heredoc syntax containing HTML/CSS/JS
- Examples:
- `Export-PermissionsToHTML` (line 1389): Responsive table, collapsible groups, copy-to-clipboard
- `Export-StorageToHTML` (line 1621): Tree visualization, sorting, filtering
- `Export-DuplicatesToHTML` (line 2235): Grouped duplicates with visual indicators
- Benefit: No external libraries; reports are self-contained single-file HTML
## Entry Points
**Main GUI Form:**
- Location: `Sharepoint_ToolBox.ps1` line 2992
- Triggers: Script execution via `.ps1` file or PowerShell IDE
- Responsibilities:
- Initialize WinForms components (form, controls, menus)
- Load and populate profiles/settings from JSON
- Register event handlers for all buttons and controls
- Run main event loop `[void]$form.ShowDialog()`
**Feature Event Handlers:**
- Location: Various in lines 4068+ (Event Handlers region)
- Examples:
- `btnPermRun.Add_Click` → Permissions report generation
- `btnStorRun.Add_Click` → Storage metrics scan
- `btnSearchRun.Add_Click` → File search
- `btnDupRun.Add_Click` → Duplicate detection
- Pattern: Validate inputs, start runspace job, launch progress animation, register cleanup callback
**Background Runspaces:**
- Entry: `Start-Job -ScriptBlock { Generate-PnPSitePermissionRpt ... }`
- Execution: PnP cmdlets execute within runspace's isolated context
- Completion: Job completion callback writes results to synchronized hashtable; timer detects and updates UI
**Language Switch:**
- Location: Menu → Language submenu (line 3011+)
- Handler: `Switch-AppLanguage` (line 4167)
- Updates: All UI labels via `Update-UILanguage` (line 2951)
## Error Handling
**Strategy:** Try/Catch with graceful degradation; errors logged to UI RichTextBox
**Patterns:**
1. **Runspace Error Handling:**
```powershell
try { $result = Get-PnPList }
catch { Write-Log "Error: $($_.Exception.Message)" "Red" }
```
2. **Connection Validation:**
- `Validate-Inputs` (line 30) checks required fields before operation
- `Connect-PnPOnline` fails if credentials invalid; caught and logged
3. **File I/O Protection:**
```powershell
if (Test-Path $path) {
try { $data = Get-Content $path -Raw | ConvertFrom-Json }
catch {} # Silently ignore JSON parse errors
}
```
4. **UI Update Safety:**
- `Write-Log` checks `if ($script:LogBox -and !$script:LogBox.IsDisposed)` before updating
- Prevents access to disposed UI objects after form close
5. **Missing Configuration Handling:**
- Settings default to English + current directory if file missing
- Profiles default to empty array if file missing
- Templates default to empty if file corrupted
## Cross-Cutting Concerns
**Logging:**
- Framework: `Write-Log` function (line 6)
- Pattern: Writes colored messages to RichTextBox + host console
- Usage: All operations log status (connecting, scanning, exporting)
- Timestamps: `Get-Date -Format 'HH:mm:ss'` prefixes each message
**Validation:**
- Entry point: `Validate-Inputs` (line 30) checks ClientID and Site URL
- Pattern: Early return if missing; user sees MessageBox with missing field hint
- Localization: Error messages use `T()` function for i18n
**Authentication:**
- Method: Interactive browser login via `Connect-PnPOnline -Interactive`
- Pattern: PnP module opens browser for Azure AD consent; token cached within session
- Credential scope: Per site connection; multiple connections supported (for multi-site operations)
- Token management: Automatic via PnP.PowerShell; no manual handling
**Asynchronous Progress:**
- Animation: `Start-ProgressAnim` (line 3845) flashes "Running..." in status label
- Polling: Timer at line 3850-3870 checks `$job.State` and synchronized hashtable every 300ms
- Cleanup: `Stop-ProgressAnim` (line 3850) stops animation when job completes
**UI Responsiveness:**
- Pattern: `[System.Windows.Forms.Application]::DoEvents()` called during long operations
- Benefit: Allows UI events (button clicks, close) to process while waiting
- Cost: Runspace jobs recommended for truly long operations (>5 second operations)
---
*Architecture analysis: 2026-04-02*