diff --git a/report-expiry.php b/report-expiry.php
index daa0a82e4bb25fd146f6bee6c39a6ae91a4a4983..16ace5c220e93cec672e3a54ba6df55711363c1c 100644
--- a/report-expiry.php
+++ b/report-expiry.php
@@ -1,48 +1,80 @@
 <?php
+/**
+ * Report certificate details.
+ *
+ * @package PHP_Cert_Reporter
+ */
 
-require __DIR__ . '/vendor/autoload.php';
-
-$data = [
-	[
-		'Filename',
-		'CN',
-		'Expires',
-		'Days Left',
-		'SAN',
-	],
-];
-
-foreach ( glob( '*.crt', GLOB_NOSORT ) as $cert ) {
-	$path = getcwd() . '/' . $cert;
-	$x509 = openssl_x509_parse( file_get_contents( $path ) );
-
-	if ( ! is_array( $x509 ) ) {
-		printf( 'Failed to parse certificate from `%1$s`%2$s', $path, "\n\n" );
-		continue;
-	}
+namespace PHP_Cert_Reporter;
+
+/**
+ * Load table renderer.
+ */
+require_once __DIR__ . '/vendor/autoload.php';
 
-	$cert_data = [
-		0 => $cert,
-		1 => $x509['subject']['CN'],
-		2 => date( 'Y-m-d H:i:s T', $x509['validTo_time_t'] ),
-		3 => (int) round( ( $x509['validTo_time_t'] - time() ) / 86400 ),
-		4 => '',
+/**
+ * Display certificate details in a table.
+ *
+ * Suitable for use in CI.
+ *
+ * @param bool $exit Exit with status code indicating if expired certificates were found.
+ */
+function report( $exit = true ): void {
+	$data = [
+		[
+			'Filename',
+			'CN',
+			'Expires',
+			'Days Left',
+			'SAN',
+		],
 	];
 
-	if ( isset( $x509['extensions']['subjectAltName'] ) ) {
-		$sans = explode( ',', $x509['extensions']['subjectAltName'] );
+	$dir_includes_expired = false;
+
+	printf( 'RESULTS FOR `%1$s`%2$s', getcwd(), "\n" );
+
+	foreach ( glob( '*.crt', GLOB_NOSORT ) as $cert ) {
+		$path = getcwd() . '/' . $cert;
+		$x509 = openssl_x509_parse( file_get_contents( $path ) );
+
+		if ( ! is_array( $x509 ) ) {
+			printf( 'Failed to parse certificate from `%1$s`%2$s', $path, "\n\n" );
+			continue;
+		}
+
+		$cert_data = [
+			0 => $cert,
+			1 => $x509['subject']['CN'],
+			2 => date( 'Y-m-d H:i:s T', $x509['validTo_time_t'] ),
+			3 => (int) round( ( $x509['validTo_time_t'] - time() ) / 86400 ),
+			4 => '',
+		];
 
-		foreach ( $sans as $i => $san ) {
-			$san        = explode( ':', $san );
-			$sans[ $i ] = array_pop( $san );
+		if ( ! $dir_includes_expired && $cert_data[3] <= 0 ) {
+			$dir_includes_expired;
 		}
 
-		$cert_data[4] = implode( ' ', $sans );
+		if ( isset( $x509['extensions']['subjectAltName'] ) ) {
+			$sans = explode( ',', $x509['extensions']['subjectAltName'] );
+
+			foreach ( $sans as $i => $san ) {
+				$san        = explode( ':', $san );
+				$sans[ $i ] = array_pop( $san );
+			}
+
+			$cert_data[4] = implode( ' ', $sans );
+		}
+
+		$data[] = $cert_data;
 	}
 
-	$data[] = $cert_data;
-}
+	$table = new \cli\Table( array_shift( $data ), $data );
+	$table->sort( 2 );
+	$table->display();
 
-$table = new \cli\Table( array_shift( $data ), $data );
-$table->sort( 2 );
-$table->display();
+	if ( $exit ) {
+		exit( $dir_includes_expired ? 1 : 0 );
+	}
+}
+report();