Automattic\WooCommerce\Internal\ProductFeed\Storage

JsonFileFeed::open │ public │ WC 1.0

{@inheritDoc}

A feed can be written across separate processes (and possibly servers), so it is created directly in the shared upload directory rather than a per-request temp directory.

Method of the class: JsonFileFeed{}

No Hooks.

Returns

string. The identifier of the feed that was started.

Usage

$JsonFileFeed = new JsonFileFeed();
$JsonFileFeed->open( ?string $resume_identifier, $entries_written ): string;
?string $resume_identifier
.
Default: null
$entries_written(int)
The number of entries already written by previous chunks.

JsonFileFeed::open() code WC 11.1.2

public function open( ?string $resume_identifier = null, int $entries_written = 0 ): string {
	$upload_dir = $this->get_upload_dir();

	$this->file_completed = false;
	$this->file_url       = null;

	if ( null !== $resume_identifier ) {
		if ( ! $this->is_valid_feed_identifier( $resume_identifier ) ) {
			throw new Exception(
				esc_html(
					sprintf(
						/* translators: %s: feed identifier */
						__( 'Invalid feed file identifier: %s', 'woocommerce' ),
						$resume_identifier
					)
				)
			);
		}

		$this->file_name = $resume_identifier;
		$this->file_path = $upload_dir['path'] . $resume_identifier;

		// The partial must still be there to append to. If it has vanished (e.g. cleaned up by the
		// host), fail rather than write a corrupt feed; the caller restarts generation from scratch.
		if ( ! is_file( $this->file_path ) ) {
			throw new Exception(
				esc_html(
					sprintf(
						/* translators: %s: file path */
						__( 'Cannot resume feed; file does not exist: %s', 'woocommerce' ),
						$this->file_path
					)
				)
			);
		}

		// Seed the entry count so add_entry()'s separator accounts for entries already written.
		$this->entry_count = $entries_written;
		$handle            = $this->open_handle( $this->file_path, 'a' );
		$this->acquire_lock( $handle );

		return $this->file_name;
	}

	$this->entry_count = 0;
	$this->file_name   = $this->generate_file_name();
	$this->file_path   = $upload_dir['path'] . $this->file_name;

	// Open with 'c' (create, do not truncate) rather than 'w' so the exclusive lock is acquired
	// *before* any existing content is cleared. An overlapping process that fails to get the lock
	// must not truncate a feed the lock holder is still writing; only once the lock is held is it
	// safe to clear stale content and write the array from the top.
	$handle = $this->open_handle( $this->file_path, 'c' );
	$this->acquire_lock( $handle );

	if ( ! ftruncate( $handle, 0 ) || ! rewind( $handle ) ) {
		fclose( $handle );
		$this->file_handle = null;
		throw new Exception(
			esc_html(
				sprintf(
					/* translators: %s: file path */
					__( 'Unable to reset feed file for writing: %s', 'woocommerce' ),
					$this->file_path
				)
			)
		);
	}

	fwrite( $handle, '[' );

	return $this->file_name;
}