SharePoint.Online.RecycleBin.SearchAndRestore.psm1

function Invoke-SharePoint.Online.RecycleBin.SearchAndRestore {

Add-Type -AssemblyName System.Windows.Forms
Import-Module PnP.PowerShell

# Connectez-vous au site SharePoint
$SiteURL = "https://tenantname.sharepoint.com/sites/sharepointsite"

# Fenêtre principale
$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Text = "Search and Restore SharePoint Online Recyle Bin"
$mainForm.Width = 1050
$mainForm.Height = 800
$mainForm.StartPosition = "CenterScreen"
$mainForm.TopMost = $true


$connectionLabel = New-Object System.Windows.Forms.Label
$connectionLabel.Text = "Disconnected"
$connectionLabel.ForeColor = [System.Drawing.Color]::Red
$connectionLabel.Location = New-Object System.Drawing.Point(600,10) 
$connectionLabel.Width = 150
$mainForm.Controls.Add($connectionLabel)


# Fonction pour afficher la fenêtre récapitulative
function Show-RestoredItemsDialog {
    param (
        [Parameter(Mandatory=$true)]
        [array]$RestoredItems
    )

    $dialogForm = New-Object System.Windows.Forms.Form
    $dialogForm.Text = "Restoration Summary"
    $dialogForm.Width = 600  # Ajustez la largeur en fonction de vos besoins
    $dialogForm.Height = 400  # Ajustez la hauteur en fonction de vos besoins
    $dialogForm.StartPosition = "CenterScreen"

    $summaryTextBox = New-Object System.Windows.Forms.TextBox
    $summaryTextBox.Multiline = $true
    $summaryTextBox.Width = 570  # Ajustez la largeur en fonction de vos besoins
    $summaryTextBox.Height = 300  # Ajustez la hauteur en fonction de vos besoins
    $summaryTextBox.ScrollBars = [System.Windows.Forms.ScrollBars]::Both
    $summaryTextBox.Location = New-Object System.Drawing.Point(10, 10)  # Ajustez la position en fonction de vos besoins

    $dialogForm.Controls.Add($summaryTextBox)

    # Construisez le texte du récapitulatif
    $summaryText = "Restored Items:`r`n`r`n"
    foreach ($item in $RestoredItems) {
        $summaryText += "Title: $($item.Title)`r`nID: $($item.ID)`r`nLocation: $($item.Location)`r`n`r`n"
    }
    $summaryTextBox.Text = $summaryText

    $closeButton = New-Object System.Windows.Forms.Button
    $closeButton.Text = "Close"
    $closeButton.Width = 80
    $closeButton.Location = New-Object System.Drawing.Point(260, 330)  # Ajustez la position en fonction de vos besoins
    $closeButton.Add_Click({ $dialogForm.Close() })

    $dialogForm.Controls.Add($closeButton)

    $dialogForm.ShowDialog()
}


#Fonction pour connaitre l'état de la connexion
function Update-ConnectionStatus {
    param (
        [Parameter(Mandatory=$true)]
        [System.Windows.Forms.Label]$StatusLabel
    )
    try {
        $context = Get-PnPContext
        if ($context -ne $null) {
            $statusLabel.Text = "Connected"
            $connectButton.Enabled = $false
            $statusLabel.ForeColor = [System.Drawing.Color]::Green
        } else {
            throw "No SharePoint context found."
        }
    } catch {
        $statusLabel.Text = "Disconnected"
        $statusLabel.ForeColor = [System.Drawing.Color]::Red
        #Write-Error "Failed to update connection status: $_"
    }
}

# Appeler la fonction avec le label approprié
Update-ConnectionStatus -StatusLabel $connectionLabel

# Champ pour l'adresse SharePoint
$siteURLLabel = New-Object System.Windows.Forms.Label
$siteURLLabel.Text = "SharePoint site URL :"
$siteURLLabel.Location = New-Object System.Drawing.Point(10,10) 
$siteURLLabel.Width = 150
$mainForm.Controls.Add($siteURLLabel)

$siteURLTextBox = New-Object System.Windows.Forms.TextBox 
$siteURLTextBox.Location = New-Object System.Drawing.Point(160,10) 
$siteURLTextBox.Width = 350
$siteURLTextBox.Text = $SiteURL  # Par défaut, utilisez la valeur de la variable $SiteURL
$mainForm.Controls.Add($siteURLTextBox)

# Bouton Connecter
$connectButton = New-Object System.Windows.Forms.Button
$connectButton.Text = "Connect"
$connectButton.Location = New-Object System.Drawing.Point(520, 8)

$connectButton.Add_Click({
    # Tentez de vous connecter à SharePoint
    try {
        Connect-PnPOnline -Url $siteURLTextBox.Text -Interactive -ValidateConnection
        Update-ConnectionStatus -StatusLabel $connectionLabel
    } catch {
        [System.Windows.Forms.MessageBox]::Show("Error while connecting : " + $_.Exception.Message)
    }
})
$mainForm.Controls.Add($connectButton)



# Champ pour le titre
$titleLabel = New-Object System.Windows.Forms.Label
$titleLabel.Text = "File or Folder Name (always use * as wildcard) :"
$titleLabel.Location = New-Object System.Drawing.Point(10, 50) 
$titleLabel.Width = 270
$mainForm.Controls.Add($titleLabel)

$titleTextBox = New-Object System.Windows.Forms.TextBox 
$titleTextBox.Location = New-Object System.Drawing.Point(285,50) 
$titleTextBox.Width = 230
$mainForm.Controls.Add($titleTextBox)

# Champ pour l'emplacement
$dirLabel = New-Object System.Windows.Forms.Label
$dirLabel.Text = "Location (always use * as wildcard) :"
$dirLabel.Location = New-Object System.Drawing.Point(10,80) 
$dirLabel.Width = 270
$mainForm.Controls.Add($dirLabel)

$dirTextBox = New-Object System.Windows.Forms.TextBox 
$dirTextBox.Location = New-Object System.Drawing.Point(285,80) 
$dirTextBox.Width = 230
$mainForm.Controls.Add($dirTextBox)

# Sélection de la date de début
$startDateLabel = New-Object System.Windows.Forms.Label
$startDateLabel.Text = "Start of Date Range (The oldest date) :"
$startDateLabel.Location = New-Object System.Drawing.Point(10,110)
$startDateLabel.Width = 270
$mainForm.Controls.Add($startDateLabel)

$startDatePicker = New-Object System.Windows.Forms.DateTimePicker 
$startDatePicker.Location = New-Object System.Drawing.Point(285,110) 
$mainForm.Controls.Add($startDatePicker)

# Sélection de la date de fin
$endDateLabel = New-Object System.Windows.Forms.Label
$endDateLabel.Text = "End of Date Range (The most recent date) :"
$endDateLabel.Location = New-Object System.Drawing.Point(10,140) 
$endDateLabel.Width = 270
$mainForm.Controls.Add($endDateLabel)

$endDatePicker = New-Object System.Windows.Forms.DateTimePicker 
$endDatePicker.Location = New-Object System.Drawing.Point(285,140) 
$mainForm.Controls.Add($endDatePicker)

# Label pour afficher "Recherche en cours..."
$statusLabel = New-Object System.Windows.Forms.Label
$statusLabel.Text = "Searching..."
$statusLabel.Location = New-Object System.Drawing.Point(120, 170)
$statusLabel.Width = 200
$statusLabel.Visible = $false 
$mainForm.Controls.Add($statusLabel)


# ListView pour afficher les résultats
$recycleBinListView = New-Object System.Windows.Forms.ListView
$recycleBinListView.View = [System.Windows.Forms.View]::Details
$recycleBinListView.Width = 1000
$recycleBinListView.Height = 500
$recycleBinListView.Location = New-Object System.Drawing.Point(20, 210)
$recycleBinListView.MultiSelect = $true

# Ajout des colonnes à la ListView
$recycleBinListView.Columns.Add("Name", 200) | Out-Null
$recycleBinListView.Columns.Add("File or Folder Type", 150) | Out-Null
$recycleBinListView.Columns.Add("Location", 250) | Out-Null
$recycleBinListView.Columns.Add("Deleted by", 200) | Out-Null
$recycleBinListView.Columns.Add("Date of deletion", 200) | Out-Null

$mainForm.Controls.Add($recycleBinListView)

# Bouton Rechercher
$searchButton = New-Object System.Windows.Forms.Button
$searchButton.Text = "Search"
$searchButton.Location = New-Object System.Drawing.Point(20, 170)
$searchButton.Add_Click({
    $mainForm.Cursor = [System.Windows.Forms.Cursors]::AppStarting
    $statusLabel.Visible = $true
    $titleCriteria = $titleTextBox.Text
    $dirCriteria = $dirTextBox.Text
    $startDate = $startDatePicker.Value.Date
    $endDate = $endDatePicker.Value.Date.AddHours(23).AddMinutes(59).AddSeconds(59)

    # Récupérez les éléments de la corbeille en fonction des critères
    $global:recycleBinItems = Get-PnPRecycleBinItem | Where-Object {
        # Si les deux critères sont spécifiés
        if ($titleCriteria -and $dirCriteria) {
            return ($_.Title -like $titleCriteria -and $_.DirName -like $dirCriteria) -and $_.DeletedDate -ge $startDate -and $_.DeletedDate -le $endDate
        }
        # Si seul le titre est spécifié
        elseif ($titleCriteria) {
            return $_.Title -like $titleCriteria -and $_.DeletedDate -ge $startDate -and $_.DeletedDate -le $endDate
        }
        # Si seul l'emplacement est spécifié
        elseif ($dirCriteria) {
            return $_.DirName -like $dirCriteria -and $_.DeletedDate -ge $startDate -and $_.DeletedDate -le $endDate
        }
        # Si aucun critère n'est spécifié
        else {
            return $_.DeletedDate -ge $startDate -and $_.DeletedDate -le $endDate
        }
    }
    $recycleBinListView.Items.Clear()
    $mainForm.Cursor = [System.Windows.Forms.Cursors]::Default
    $statusLabel.Visible = $false 
    # Si aucun élément n'a été trouvé
    if (-not $global:recycleBinItems) {
        [System.Windows.Forms.MessageBox]::Show("No files or folders found based on your search criteria. Try conducting a new search with different parameters.", "No result found", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Information)
    } else {
        $global:recycleBinItems | ForEach-Object {
            $item = New-Object System.Windows.Forms.ListViewItem($_.Title)
            $item.SubItems.Add($_.ItemType.ToString())
            $item.SubItems.Add($_.DirName)
            $item.SubItems.Add($_.DeletedByName)
            $item.SubItems.Add($_.DeletedDate.ToString())
            $recycleBinListView.Items.Add($item)
        }
    }
})

$mainForm.Controls.Add($searchButton)

# Label pour afficher "Restoring..."
$restoringLabel = New-Object System.Windows.Forms.Label
$restoringLabel.Text = "Restoring..."
$restoringLabel.Location = New-Object System.Drawing.Point(120, 720)
$restoringLabel.Width = 200
$restoringLabel.Visible = $false
$mainForm.Controls.Add($restoringLabel)

# Bouton Restaurer
$restoreButton = New-Object System.Windows.Forms.Button
$restoreButton.Text = "Restore"
$restoreButton.Location = New-Object System.Drawing.Point(20, 720)
$restoreButton.Add_Click({
$selectedItems = $recycleBinListView.SelectedItems
# Créez un tableau pour stocker les éléments restaurés
$restoredItems = @()

    foreach ($listViewItem in $selectedItems) {
    $selectedTitle = $listViewItem.Text
    $itemToRestore = $global:recycleBinItems | Where-Object { $_.Title -eq $selectedTitle }

    if ($itemToRestore) {
        $itemRestoredTitle = $itemToRestore.Title
        $itemRestoredId = $itemToRestore.Id.Guid
        $itemRestoredDir = $itemToRestore.DirName
        
        # Affichez le texte "Restoring..."
        $restoringLabel.Visible = $true

        # Restaurez l'élément
        Restore-PnPRecycleBinItem -Identity $itemToRestore.Id.Guid -Force

        # Ajoutez l'élément restauré au tableau
        $restoredItems += [PSCustomObject]@{
            "Title" = $itemRestoredTitle
            "ID" = $itemRestoredId
            "Location" = $itemRestoredDir
        }
        # Masquez le texte "Restoring..."
        $restoringLabel.Visible = $false
    } else {
        [System.Windows.Forms.MessageBox]::Show("No file or folder found for : $selectedTitle.", "Error", [System.Windows.Forms.MessageBoxButtons]::OK, [System.Windows.Forms.MessageBoxIcon]::Error)
    }
}

    # Affichez une fenêtre récapitulative
    Show-RestoredItemsDialog -RestoredItems $restoredItems
    $searchButton.PerformClick() 
})

$mainForm.Controls.Add($restoreButton)

# Bouton Quitter
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Text = "Quit"
$cancelButton.Location = New-Object System.Drawing.Point(930, 720)
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$mainForm.Controls.Add($cancelButton)

$result = $mainForm.ShowDialog()

if ($result -eq [System.Windows.Forms.DialogResult]::Cancel) {
    Disconnect-PnPOnline
    exit
}
}