insert_with_markers( string $filename, string $marker_in, array|string $insertion, bool $is_regex = false, string|null $marker_out = null )

Inserts an array of strings into a file (.htaccess), placing it between BEGIN and END markers.


Description

Replaces existing marked info. Retains surrounding data. Creates file if none exists.


Parameters

$filename

(string) (Required) The path to the file to alter (e.g. .htaccess).

$marker_in

(string) (Required) The marker to alter (matches lines in the form of # BEGIN $marker and # END $marker in the file).

$insertion

(array|string) (Required) The new content to insert.

$is_regex

(bool) (Optional) Set to 'true' if $marker_in is a regex. The regex delimiter is '/'; you must escape this character if it occurs in your marker pattern. Default 'false'.

Default value: false

$marker_out

(string|null) (Optional) The marker to write. Only needed if $is_regex is true.

Default value: null


Return

(bool) True on write success, false on failure.


Source

File: wp-admin/includes/misc.php

function insert_with_markers(
	$filename,
	$marker_in,
	$insertion,
	$is_regex = false,
	$marker_out = null
) {
	if ( ! file_exists( $filename ) ) {
		if ( ! is_writable( dirname( $filename ) ) ) {
			return false;
		}
		if ( ! touch( $filename ) ) {
			return false;
		}
	} elseif ( ! is_writeable( $filename ) ) {
		return false;
	}

	if ( ! is_array( $insertion ) ) {
		$insertion = explode( "\n", $insertion );
	}

	if ( null === $marker_out ) {
		if ( $is_regex ) {
			// The marker to write must be specified as a string!
			return false;
		}
		$marker_out = $marker_in;
	}

	$start_marker_in  = "# BEGIN {$marker_in}";
	$end_marker_in    = "# END {$marker_in}";
	$start_marker_out = "# BEGIN {$marker_out}";
	$end_marker_out   = "# END {$marker_out}";

	if ( ! $is_regex ) {
		$start_marker_in = preg_quote( $start_marker_in, '/' );
		$end_marker_in   = preg_quote( $end_marker_in, '/' );
	}

	$start_marker_in = "/{$start_marker_in}/";
	$end_marker_in   = "/{$end_marker_in}/";

	$fp = fopen( $filename, 'r+' );
	if ( ! $fp ) {
		return false;
	}

	// Attempt to get a lock. If the filesystem supports locking, this will
	// block until the lock is acquired.
	flock( $fp, LOCK_EX );

	$lines = array();
	while ( ! feof( $fp ) ) {
		$lines[] = rtrim( fgets( $fp ), "\r\n" );
	}

	// Split out the existing file into the preceding lines, and those that
	// appear after the marker.
	$pre_lines = $post_lines = $existing_lines = array();
	$found_marker = $found_end_marker = false;
	foreach ( $lines as $line ) {
		if ( ! $found_marker && preg_match( $start_marker_in, $line ) ) {
			$found_marker = true;
			continue;
		} elseif ( ! $found_end_marker && preg_match( $end_marker_in, $line ) ) {
			$found_end_marker = true;
			continue;
		}
		if ( ! $found_marker ) {
			$pre_lines[] = $line;
		} elseif ( $found_marker && $found_end_marker ) {
			$post_lines[] = $line;
		} else {
			$existing_lines[] = $line;
		}
	}

	// Check to see if there was a change
	if ( $existing_lines === $insertion ) {
		flock( $fp, LOCK_UN );
		fclose( $fp );

		return true;
	}

	// Generate the new file data
	$new_file_data = implode( "\n", array_merge(
		$pre_lines,
		array( $start_marker_out ),
		$insertion,
		array( $end_marker_out ),
		$post_lines
	) );

	// Write to the start of the file, and truncate it to that length
	fseek( $fp, 0 );
	$bytes = fwrite( $fp, $new_file_data );
	if ( $bytes ) {
		ftruncate( $fp, ftell( $fp ) );
	}
	fflush( $fp );
	flock( $fp, LOCK_UN );
	fclose( $fp );

	return (bool) $bytes;
}


Changelog

Changelog
Version Description
1.0.0 Added $marker_out and $is_regex parameters.
WP-1.5.0 Introduced.