فهرست منبع

convert to using traits

Tim Fry 1 سال پیش
والد
کامیت
1eb43cf2fd

+ 24 - 0
app_languages.php

@@ -24,6 +24,30 @@ $text['title-maintenance']['zh-cn'] = '';
 $text['title-maintenance']['ja-jp'] = '';
 $text['title-maintenance']['ja-jp'] = '';
 $text['title-maintenance']['ko-kr'] = '';
 $text['title-maintenance']['ko-kr'] = '';
 
 
+$text['message-no_records']['en-us'] = 'No records to process';
+$text['message-no_records']['en-gb'] = 'No records to process';
+$text['message-no_records']['ar-eg'] = '';
+$text['message-no_records']['de-at'] = '';
+$text['message-no_records']['de-ch'] = '';
+$text['message-no_records']['de-de'] = '';
+$text['message-no_records']['es-cl'] = '';
+$text['message-no_records']['es-mx'] = '';
+$text['message-no_records']['fr-ca'] = '';
+$text['message-no_records']['fr-fr'] = '';
+$text['message-no_records']['he-il'] = '';
+$text['message-no_records']['it-it'] = '';
+$text['message-no_records']['nl-nl'] = '';
+$text['message-no_records']['pl-pl'] = '';
+$text['message-no_records']['pt-br'] = '';
+$text['message-no_records']['pt-pt'] = '';
+$text['message-no_records']['ro-ro'] = '';
+$text['message-no_records']['ru-ru'] = '';
+$text['message-no_records']['sv-se'] = '';
+$text['message-no_records']['uk-ua'] = '';
+$text['message-no_records']['zh-cn'] = '';
+$text['message-no_records']['ja-jp'] = '';
+$text['message-no_records']['ko-kr'] = '';
+
 $text['label-server_timestamp']['en-us'] = 'Server Timestamp';
 $text['label-server_timestamp']['en-us'] = 'Server Timestamp';
 $text['label-server_timestamp']['en-gb'] = 'Server Timestamp';
 $text['label-server_timestamp']['en-gb'] = 'Server Timestamp';
 $text['label-server_timestamp']['ar-eg'] = '';
 $text['label-server_timestamp']['ar-eg'] = '';

+ 1 - 0
maintenance.php

@@ -30,6 +30,7 @@ Tim Fry <[email protected]>
 require_once dirname(__DIR__, 2) . '/resources/require.php';
 require_once dirname(__DIR__, 2) . '/resources/require.php';
 require_once "resources/check_auth.php";
 require_once "resources/check_auth.php";
 require_once "resources/paging.php";
 require_once "resources/paging.php";
+require_once __DIR__ . '/resources/functions.php';
 
 
 if (permission_exists('maintenance_view')) {
 if (permission_exists('maintenance_view')) {
 	// permission granted
 	// permission granted

+ 16 - 18
maintenance_logs.php

@@ -141,14 +141,14 @@
 
 
 //get the list
 //get the list
 	$sql = "select"
 	$sql = "select"
-		. "  maintenance_log_uuid"
-		. "  ,maintenance_log_application"
-		. "  ,to_timestamp(maintenance_log_epoch)::timestamptz as maintenance_log_epoch"
-//		. "  ,maintenance_log_epoch"
-		. "  ,maintenance_log_message"
-		. "  ,maintenance_log_status"
+		. " maintenance_log_uuid"
+		. ", domain_uuid"
+		. ", maintenance_log_application"
+		. ", to_timestamp(maintenance_log_epoch)::timestamptz as maintenance_log_epoch"
+		. ", maintenance_log_message"
+		. ", maintenance_log_status"
 		. " from"
 		. " from"
-		. "  v_maintenance_logs"
+		. " v_maintenance_logs"
 	;
 	;
 //	if (isset($search)) {
 //	if (isset($search)) {
 //		$sql .= "and ( \n";
 //		$sql .= "and ( \n";
@@ -201,12 +201,6 @@
 	echo "	<div style='clear: both;'></div>\n";
 	echo "	<div style='clear: both;'></div>\n";
 	echo "</div>\n";
 	echo "</div>\n";
 
 
-	if (permission_exists('maintenance_log_add') && $maintenance_logs) {
-		echo modal::create(['id'=>'modal-copy','type'=>'copy','actions'=>button::create(['type'=>'button','label'=>$text['button-continue'],'icon'=>'check','id'=>'btn_copy','style'=>'float: right; margin-left: 15px;','collapse'=>'never','onclick'=>"modal_close(); list_action_set('copy'); list_form_submit('form_list');"])]);
-	}
-	if (permission_exists('maintenance_log_edit') && $maintenance_logs) {
-		echo modal::create(['id'=>'modal-toggle','type'=>'toggle','actions'=>button::create(['type'=>'button','label'=>$text['button-continue'],'icon'=>'check','id'=>'btn_toggle','style'=>'float: right; margin-left: 15px;','collapse'=>'never','onclick'=>"modal_close(); list_action_set('toggle'); list_form_submit('form_list');"])]);
-	}
 	if (permission_exists('maintenance_log_delete') && $maintenance_logs) {
 	if (permission_exists('maintenance_log_delete') && $maintenance_logs) {
 		echo modal::create(['id'=>'modal-delete','type'=>'delete','actions'=>button::create(['type'=>'button','label'=>$text['button-continue'],'icon'=>'check','id'=>'btn_delete','style'=>'float: right; margin-left: 15px;','collapse'=>'never','onclick'=>"modal_close(); list_action_set('delete'); list_form_submit('form_list');"])]);
 		echo modal::create(['id'=>'modal-delete','type'=>'delete','actions'=>button::create(['type'=>'button','label'=>$text['button-continue'],'icon'=>'check','id'=>'btn_delete','style'=>'float: right; margin-left: 15px;','collapse'=>'never','onclick'=>"modal_close(); list_action_set('delete'); list_form_submit('form_list');"])]);
 	}
 	}
@@ -220,14 +214,15 @@
 
 
 	echo "<table class='list'>\n";
 	echo "<table class='list'>\n";
 	echo "<tr class='list-header'>\n";
 	echo "<tr class='list-header'>\n";
-//	if (permission_exists('maintenance_log_delete')) {
+	if (permission_exists('maintenance_log_delete')) {
 		echo "	<th class='checkbox'>\n";
 		echo "	<th class='checkbox'>\n";
 		echo "		<input type='checkbox' id='checkbox_all' name='checkbox_all' onclick='list_all_toggle();' ".($maintenance_logs ?: "style='visibility: hidden;'").">\n";
 		echo "		<input type='checkbox' id='checkbox_all' name='checkbox_all' onclick='list_all_toggle();' ".($maintenance_logs ?: "style='visibility: hidden;'").">\n";
 		echo "	</th>\n";
 		echo "	</th>\n";
-//	}
+	}
 	if ($show == 'all' && permission_exists('maintenance_log_all')) {
 	if ($show == 'all' && permission_exists('maintenance_log_all')) {
 		echo th_order_by('domain_name', $text['label-domain'], $order_by, $order);
 		echo th_order_by('domain_name', $text['label-domain'], $order_by, $order);
 	}
 	}
+	echo "<th class='left'>".$text['label-domain']."</th>\n";
 	echo "<th class='left'>".$text['label-application']."</th>\n";
 	echo "<th class='left'>".$text['label-application']."</th>\n";
 	echo "<th class='left'>".$text['label-server_timestamp']."</th>\n";
 	echo "<th class='left'>".$text['label-server_timestamp']."</th>\n";
 	echo "<th class='left'>".$text['label-status']."</th>\n";
 	echo "<th class='left'>".$text['label-status']."</th>\n";
@@ -238,19 +233,22 @@
 	echo "</tr>\n";
 	echo "</tr>\n";
 
 
 	if (is_array($maintenance_logs) && @sizeof($maintenance_logs) != 0) {
 	if (is_array($maintenance_logs) && @sizeof($maintenance_logs) != 0) {
+		$domains = maintenance_service::get_domains($database);
 		$x = 0;
 		$x = 0;
 		foreach ($maintenance_logs as $row) {
 		foreach ($maintenance_logs as $row) {
+			$application_name = ucwords(str_replace('_', ' ', $row['maintenance_log_application']));
+			$domain_name = $domains[$row['domain_uuid']] ?: 'Global';
 			if (permission_exists('maintenance_log_edit')) {
 			if (permission_exists('maintenance_log_edit')) {
 				$list_row_url = "maintenance_log_edit.php?id=".urlencode($row['maintenance_log_uuid']);
 				$list_row_url = "maintenance_log_edit.php?id=".urlencode($row['maintenance_log_uuid']);
 			}
 			}
 			echo "<tr class='list-row' href='".$list_row_url."'>\n";
 			echo "<tr class='list-row' href='".$list_row_url."'>\n";
-//			if (permission_exists('maintenance_log_delete')) {
+			if (permission_exists('maintenance_log_delete')) {
 				echo "	<td class='checkbox'>\n";
 				echo "	<td class='checkbox'>\n";
 				echo "		<input type='checkbox' name='maintenance_logs[$x][checked]' id='checkbox_".$x."' value='true' onclick=\"if (!this.checked) { document.getElementById('checkbox_all').checked = false; }\">\n";
 				echo "		<input type='checkbox' name='maintenance_logs[$x][checked]' id='checkbox_".$x."' value='true' onclick=\"if (!this.checked) { document.getElementById('checkbox_all').checked = false; }\">\n";
 				echo "		<input type='hidden' name='maintenance_logs[$x][uuid]' value='".escape($row['maintenance_log_uuid'])."' />\n";
 				echo "		<input type='hidden' name='maintenance_logs[$x][uuid]' value='".escape($row['maintenance_log_uuid'])."' />\n";
 				echo "	</td>\n";
 				echo "	</td>\n";
-//			}
-			$application_name = ucwords(str_replace('_', ' ', $row['maintenance_log_application']));
+			}
+			echo "	<td class='left'>$domain_name</td>\n";
 			echo "	<td class='left'>".escape($application_name)."</td>\n";
 			echo "	<td class='left'>".escape($application_name)."</td>\n";
 			echo "	<td class='left'>".escape($row['maintenance_log_epoch'])."</td>\n";
 			echo "	<td class='left'>".escape($row['maintenance_log_epoch'])."</td>\n";
 			echo "	<td class='left'>".escape($row['maintenance_log_status'])."</td>\n";
 			echo "	<td class='left'>".escape($row['maintenance_log_status'])."</td>\n";

+ 199 - 21
resources/classes/maintenance_logs.php

@@ -31,34 +31,212 @@
  *
  *
  * @author Tim Fry <[email protected]>
  * @author Tim Fry <[email protected]>
  */
  */
-class maintenance_logs implements database_maintenance {
-
-	public function database_maintenance(database $database, settings $settings): void {
-		//get retention days
-		$days = $settings->get($this->database_retention_category(), $this->database_retention_subcategory(), '');
-		//look for old entries
-		if (!empty($days)) {
-			$sql = "delete from v_maintenance_logs where insert_date < NOW() - INTERVAL '$days days'";
-			$database->execute($sql);
-			if ($database->message['code'] === '200') {
-				maintenance_service::log_write($this, "Removed maintenance log entries older than $days days.");
-			} else {
-				maintenance_service::log_write($this, "Failed to clear entries", maintenance_service::LOG_ERROR);
-			}
+class maintenance_logs {
+
+	use database_maintenance;
+
+	const APP_NAME = 'maintenance_logs';
+	const APP_UUID = '5be7b4c2-1a4f-4236-b91a-60e3c33904d7';
+	const PERMISSION_PREFIX = 'maintenance_log_';
+	const LIST_PAGE = 'maintenance_logs.php';
+	const TABLE = 'maintenance_logs';
+	const UUID_PREFIX = 'maintenance_log_';
+	const TOGGLE_FIELD = 'maintenance_log_enable';
+	const TOGGLE_VALUES = ['true', 'false'];
+
+	private $database;
+	private $settings;
+	private $domain_uuid;
+	private $user_uuid;
+
+	public function __construct(database $database, settings $settings) {
+		if ($database !== null) {
+			$this->database = $database;
+		} else {
+			$this->database = new $database;
+		}
+
+		$this->domain_uuid = $_SESSION['domain_uuid'] ?? '';
+		$this->user_uuid = $_SESSION['user_uuid'] ?? '';
+
+		if ($settings !== null) {
+			$this->settings = $settings;
 		} else {
 		} else {
-			maintenance_service::log_write($this, 'Retention days not set', maintenance_service::LOG_ERROR);
+			$this->settings = new settings([
+				'database' => $database
+				, 'domain_uuid' => $this->domain_uuid
+				, 'user_uuid' => $this->user_uuid
+			]);
 		}
 		}
+
+		$database->app_name = self::APP_NAME;
+		$database->app_uuid = self::APP_UUID;
+	}
+
+	public static function database_maintenance_sql(string $domain_uuid, string $retention_days): string {
+		return "delete from v_maintenance_logs"
+			. " where insert_date < NOW() - INTERVAL '$retention_days days'"
+			. " and (domain_uuid = '$domain_uuid' or domain_uuid is null)"
+		;
 	}
 	}
 
 
-	public function database_retention_category(): string {
-		return 'maintenance';
+	/**
+	 * delete records
+	 */
+	public function delete(array $records) {
+		//add multi-lingual support
+		$language = new text;
+		$text = $language->get();
+
+		if (!permission_exists(self::PERMISSION_PREFIX . 'delete') || empty($records)) {
+			message::add($text['message-no_records'], 'negative');
+			header('Location: ' . self::LIST_PAGE);
+			exit;
+		}
+
+		//validate the token
+		$token = new token;
+		if (!$token->validate($_SERVER['PHP_SELF'])) {
+			message::add($text['message-invalid_token'], 'negative');
+			header('Location: ' . self::LIST_PAGE);
+			exit;
+		}
+
+		//delete multiple records by building an array of records to remove
+		$remove_array = [];
+		foreach ($records as $x => $record) {
+			if (!empty($record['checked']) && $record['checked'] == 'true' && is_uuid($record['uuid'])) {
+				$remove_array[self::TABLE][$x][self::UUID_PREFIX . 'uuid'] = $record['uuid'];
+				$remove_array[self::TABLE][$x]['domain_uuid'] = $this->domain_uuid;
+			}
+		}
+
+		//delete the checked rows
+		if (!empty($remove_array)) {
+			//execute delete
+			$this->database->delete($remove_array);
+			//set message
+			message::add($text['message-delete']);
+		}
 	}
 	}
 
 
-	public function database_retention_subcategory(): string {
-		return 'database_retention_days';
+	/**
+	 * toggle records
+	 */
+	public function toggle(array $records) {
+		//add multi-lingual support
+		$language = new text;
+		$text = $language->get();
+
+		//check that we have something to do
+		if (empty($records) || !permission_exists(self::PERMISSION_PREFIX . 'edit')) {
+			message::add($text['message-no_records'], 'negative');
+			header('Location: ' . self::LIST_PAGE);
+			return;
+		}
+
+		//validate the token
+		$token = new token;
+		if (!$token->validate($_SERVER['PHP_SELF'])) {
+			message::add($text['message-invalid_token'], 'negative');
+			header('Location: ' . self::LIST_PAGE);
+			exit;
+		}
+
+		//toggle the checked records to get current toggle state
+		$uuids = [];
+		foreach ($records as $x => $record) {
+			if (!empty($record['checked']) && $record['checked'] == 'true' && is_uuid($record['uuid'])) {
+				$uuids[] = "'" . $record['uuid'] . "'";
+			}
+		}
+		if (!empty($uuids)) {
+			$sql = "select " . self::UUID_PREFIX . "uuid as uuid, " . self::TOGGLE_FIELD . " as toggle from v_" . self::TABLE . " ";
+			$sql .= "where (domain_uuid = :domain_uuid or domain_uuid is null) ";
+			$sql .= "and " . self::UUID_PREFIX . "uuid in (" . implode(', ', $uuids) . ") ";
+			$parameters['domain_uuid'] = $this->domain_uuid;
+
+			$rows = $this->database->select($sql, $parameters, 'all');
+			if (!empty($rows)) {
+				$states = [];
+				foreach ($rows as $row) {
+					$states[$row['uuid']] = $row['toggle'];
+				}
+			}
+		}
+
+		//build update array
+		$x = 0;
+		$array = [];
+		foreach ($states as $uuid => $state) {
+			$array[self::TABLE][$x][self::UUID_PREFIX . 'uuid'] = $uuid;
+			$array[self::TABLE][$x][self::TOGGLE_FIELD] = $state == self::TOGGLE_VALUES[0] ? self::TOGGLE_VALUES[1] : self::TOGGLE_VALUES[0];
+			$x++;
+		}
+
+		//save the changes
+		if (!empty($array)) {
+
+			//save the array
+			$database->app_name = self::APP_NAME;
+			$database->app_uuid = self::APP_UUID;
+			$this->database->save($array);
+
+			//set message
+			message::add($text['message-toggle']);
+		}
 	}
 	}
 
 
-	public function database_retention_default_value(): string {
-		return '30';
+	/**
+	 * copy records
+	 */
+	public function copy(array $records) {
+		//check that we have something to do
+		if (empty($records) || !permission_exists(self::PERMISSION_PREFIX . 'add')) {
+			return;
+		}
+		//add multi-lingual support
+		$language = new text;
+		$text = $language->get();
+
+		//validate the token
+		$token = new token;
+		if (!$token->validate($_SERVER['PHP_SELF'])) {
+			message::add($text['message-invalid_token'], 'negative');
+			header('Location: ' . self::LIST_PAGE);
+			exit;
+		}
+
+
+		//get checked records
+		$uuids = [];
+		foreach ($records as $record) {
+			if (!empty($record['checked']) && $record['checked'] == 'true' && is_uuid($record['uuid'])) {
+				$uuids[] = "'" . $record['uuid'] . "'";
+			}
+		}
+
+		//create insert array from existing data
+		if (!empty($uuids)) {
+			$sql = "select * from v_" . self::TABLE
+				. " where (domain_uuid = :domain_uuid or domain_uuid is null)"
+				. " and " . self::UUID_PREFIX . "uuid in (" . implode(', ', $uuids) . ")";
+			$parameters['domain_uuid'] = $this->domain_uuid;
+			$rows = $this->database->select($sql, $parameters, 'all');
+			if (!empty($rows)) {
+				$array = [];
+				foreach ($rows as $x => $row) {
+					//copy data
+					$array[self::TABLE][$x] = $row;
+					//overwrite
+					$array[self::TABLE][$x][self::UUID_PREFIX . 'uuid'] = uuid();
+					$array[self::TABLE][$x]['bridge_description'] = trim($row['bridge_description'] . ' (' . $text['label-copy'] . ')');
+				}
+				$this->database->save($array);
+			}
+
+			//set message
+			message::add($text['message-copy']);
+		}
 	}
 	}
 }
 }

+ 31 - 10
resources/classes/maintenance_service.php

@@ -98,10 +98,10 @@ class maintenance_service extends service {
 	protected static function set_cli_options() {
 	protected static function set_cli_options() {
 		//add a new command line option
 		//add a new command line option
 		self::append_cli_option(cli_option::new()
 		self::append_cli_option(cli_option::new()
-			->short_option('i')
-			->long_option('immediate')
-			->description('Launch maintenance services immediately on startup')
-			->functions(['set_immediate'])
+				->short_option('i')
+				->long_option('immediate')
+				->description('Launch maintenance services immediately on startup')
+				->functions(['set_immediate'])
 		);
 		);
 	}
 	}
 
 
@@ -190,7 +190,7 @@ class maintenance_service extends service {
 		}
 		}
 
 
 		//main loop
 		//main loop
-		while($this->running) {
+		while ($this->running) {
 			//wait until the time matches requested time of day
 			//wait until the time matches requested time of day
 			do {
 			do {
 				$now = date('H:i');
 				$now = date('H:i');
@@ -384,16 +384,17 @@ class maintenance_service extends service {
 	/**
 	/**
 	 * Saves the logs in an array in order to write them all at once. This is to remove the number of times the database will try to
 	 * Saves the logs in an array in order to write them all at once. This is to remove the number of times the database will try to
 	 * be written to during the many worker processes to improve performance similar to an atomic commit.
 	 * be written to during the many worker processes to improve performance similar to an atomic commit.
-	 * @param database_maintenance|filesystem_maintenance|string $worker
+	 * @param database_maintenance|filesystem_maintenance|string $worker_or_classname
 	 * @param string $message
 	 * @param string $message
 	 */
 	 */
-	public static function log_write($worker, string $message, string $status = self::LOG_OK) {
+	public static function log_write($worker_or_classname, string $message, string $domain_uuid = '', string $status = self::LOG_OK) {
 		require_once dirname(__DIR__) . '/functions.php';
 		require_once dirname(__DIR__) . '/functions.php';
-		$classname = get_classname($worker);
+		$classname = get_classname($worker_or_classname);
 		//protect against hijacking the log writer from a non maintenance worker
 		//protect against hijacking the log writer from a non maintenance worker
 		if (self::$logs !== null && (has_interface($classname, 'database_maintenance') || has_interface($classname, 'filesystem_maintenance'))) {
 		if (self::$logs !== null && (has_interface($classname, 'database_maintenance') || has_interface($classname, 'filesystem_maintenance'))) {
 			$row_index = count(self::$logs);
 			$row_index = count(self::$logs);
-			self::$logs[$row_index]['maintenance_log_uuid']   = uuid();
+			self::$logs[$row_index]['maintenance_log_uuid'] = uuid();
+			self::$logs[$row_index]['maintenance_log_domain_uuid'] = $domain_uuid;
 			self::$logs[$row_index]['maintenance_log_application'] = $classname;
 			self::$logs[$row_index]['maintenance_log_application'] = $classname;
 			self::$logs[$row_index]['maintenance_log_epoch'] = time();
 			self::$logs[$row_index]['maintenance_log_epoch'] = time();
 			self::$logs[$row_index]['maintenance_log_message'] = $message;
 			self::$logs[$row_index]['maintenance_log_message'] = $message;
@@ -401,6 +402,27 @@ class maintenance_service extends service {
 		}
 		}
 	}
 	}
 
 
+	/**
+	 * Returns a list of domains with the domain_uuid as the key and the domain_name as the value
+	 * @param database $database
+	 * @return array Domain uuid as key and domain name as value
+	 */
+	public static function get_domains(database $database): array {
+		$domain = new domains();
+		$domain->all();
+		$domains = [];
+		$sql = "select domain_uuid, domain_name"
+			. " from v_domains"
+		;
+		$records = $database->select($sql);
+		if (!empty($records)) {
+			foreach($records as $row) {
+				$domains[$row['domain_uuid']] = $row['domain_name'];
+			}
+		}
+		return $domains;
+	}
+
 	/**
 	/**
 	 * Returns the number of seconds passed since the file was created
 	 * Returns the number of seconds passed since the file was created
 	 * @param string $file Full path and file name
 	 * @param string $file Full path and file name
@@ -471,5 +493,4 @@ class maintenance_service extends service {
 	public static function years_since_created(string $file): int {
 	public static function years_since_created(string $file): int {
 		return floor(self::weeks_since_created($file) / 52);
 		return floor(self::weeks_since_created($file) / 52);
 	}
 	}
-
 }
 }

+ 31 - 5
resources/interfaces/database_maintenance.php

@@ -30,9 +30,35 @@
  *
  *
  * @author Tim Fry <[email protected]>
  * @author Tim Fry <[email protected]>
  */
  */
-interface database_maintenance {
-	public function database_maintenance(database $database, settings $settings): void;
-	public function database_retention_category(): string;
-	public function database_retention_subcategory(): string;
-	public function database_retention_default_value(): string;
+trait database_maintenance {
+	//
+	//override the values in the class that is using the trait or leave as default
+	//
+	public static $database_maintenance_application = self::class;
+	public static $database_retention_category = self::class;
+	public static $database_retention_subcategory = 'database_retention_days';
+	public static $database_retention_default_value = '30';
+
+	//class must implement this method
+	abstract public static function database_maintenance_sql(string $domain_uuid, string $retention_days): string;
+
+	public static function database_maintenance(database $database, settings $settings): void {
+		//get retention days
+		$days = $settings->get(self::$database_retention_category, self::$database_retention_subcategory, '');
+		//look for old entries
+		if (!empty($days) && is_numeric($days)) {
+			$domains = maintenance_service::get_domains($database);
+			foreach ($domains as $domain_uuid => $domain_name) {
+				$database->execute(self::get_database_maintenance_sql_statement($domain_uuid, $domain_name, $days));
+				if ($database->message['code'] === '200') {
+					maintenance_service::log_write(self::$database_maintenance_application, "Removed maintenance log entries older than $days days for domain $domain_name.");
+				} else {
+					maintenance_service::log_write(self::$database_maintenance_application, "Failed to clear entries", $domain_uuid, maintenance_service::LOG_ERROR);
+				}
+			}
+		} else {
+			//database retention not set or not a valid number
+			maintenance_service::log_write(self::$database_maintenance_application, 'Retention days not set', '', maintenance_service::LOG_ERROR);
+		}
+	}
 }
 }

+ 45 - 5
resources/interfaces/filesystem_maintenance.php

@@ -30,9 +30,49 @@
  *
  *
  * @author Tim Fry <[email protected]>
  * @author Tim Fry <[email protected]>
  */
  */
-interface filesystem_maintenance {
-	public function filesystem_maintenance(database $database, settings $settings): void;
-	public function filesystem_retention_category(): string;
-	public function filesystem_retention_subcategory(): string;
-	public function filesystem_retention_default_value(): string;
+trait filesystem_maintenance {
+	//
+	//override the values in the class that is using the trait or leave as default
+	//
+	public static $filesystem_maintenance_application = self::class;
+	public static $filesystem_retention_category = self::class;
+	public static $filesystem_retention_subcategory = 'filesystem_retention_days';
+	public static $filesystem_retention_default_value = '30';
+
+	//class must implement this method
+	abstract public static function filesystem_maintenance_files(string $domain_uuid, string $domain_name, string $retention_days): array;
+
+	/**
+	 * A generic file remover
+	 * @param database $database
+	 * @param settings $settings
+	 * @return void
+	 */
+	public static function filesystem_maintenance(database $database, settings $settings): void {
+		//get retention days
+		$days = $settings->get(self::$filesystem_retention_category, self::$filesystem_retention_subcategory, '');
+		//look for old entries
+		if (!empty($days) && is_numeric($days)) {
+			$domains = maintenance_service::get_domains($database);
+			//loop over domains
+			foreach ($domains as $domain_uuid => $domain_name) {
+				//loop over each file in the domain
+				foreach (self::filesystem_maintenance_files($domain_uuid, $domain_name, $days) as $file) {
+					//check if it is old enough
+					if (maintenance_service::days_since_created($file) > $days) {
+						if (unlink($file)) {
+							//successfully deleted file
+							maintenance_service::log_write(self::$filesystem_maintenance_application, "Removed $file", $domain_uuid);
+						} else {
+							//failed
+							maintenance_service::log_write(self::$filesystem_maintenance_application, "Unabled to remove $file", $domain_uuid, maintenance_service::LOG_ERROR);
+						}
+					}
+				}
+			}
+		} else {
+			//filesystem retention not set or not a valid number
+			maintenance_service::log_write(self::$filesystem_maintenance_application, 'Retention days not set', '', maintenance_service::LOG_ERROR);
+		}
+	}
 }
 }