Skip to content
← Back to Functions
Code

Export Stream Planner

Plans streamed CSV/JSON exports with headers, chunk size, and filename policy.

Function signature

ogPlanExportStream(request = array(), policy = array())

Categories

  • Security

Parameters

requestExport request data. Recognized keys: `chunk_size`, `columns`, `format`.policyAllowed formats, columns, filename prefix, and chunk limits. Recognized keys: `allowed_columns`, `allowed_formats`, `filename_prefix`.

Return value

Short public-safe status message.

  • format
  • filename
  • content_type
  • columns
  • chunk_size
  • streaming

Compatibility

Existing function name and call order preserved; metadata signature corrected to source.

Minimum PHP version: 7.4

Security notes

Validate request method, identity, permissions, policy arrays, URLs, signatures, and caller-owned allowlists before use; keep secrets and internal paths out of public output.

Code

<?php

/*
 * Copyright (c) 2026 Jeffery L. Paris <jparis@phpog.com>.
 * Free for personal and internal use. Paid project use requires visible credit
 * to Jeffery L. Paris. Corporate use requires a paid license fee unless a
 * separate written license states otherwise.
 */

/**
 * Plans streamed CSV/JSON exports with headers, chunk size, and filename policy.
 *
 * The helper does not execute queries or buffer data. It returns a safe export plan that a controller
 * can use for explicit streaming output.
 *
 * @param array $request Export request data.
 * @param array $policy Allowed formats, columns, filename prefix, and chunk limits.
 * @return array Export stream plan.
 */
function ogPlanExportStream($request = array(), $policy = array()) {
	$result = array(
		'success' => false,
		'message' => '',
		'data' => array()
	);

	if (!is_array($request)) {
		$result['message'] = 'Export request must be an array.';
		return $result;
	}
	if (!is_array($policy)) {
		$policy = array();
	}

	$allowed_formats = array('csv', 'json');
	if (!empty($policy['allowed_formats']) && is_array($policy['allowed_formats'])) {
		$allowed_formats = $policy['allowed_formats'];
	}

	$format = 'csv';
	if (!empty($request['format'])) {
		$format = strtolower(trim((string)$request['format']));
	}
	if (!in_array($format, $allowed_formats, true)) {
		$result['message'] = 'Export format is not allowed.';
		return $result;
	}

	$allowed_columns = array();
	if (!empty($policy['allowed_columns']) && is_array($policy['allowed_columns'])) {
		$allowed_columns = $policy['allowed_columns'];
	}
	$columns = array();
	if (!empty($request['columns']) && is_array($request['columns'])) {
		foreach ($request['columns'] as $column) {
			$column = preg_replace('/[^a-zA-Z0-9_]/', '', (string)$column);
			if (!empty($column) && (empty($allowed_columns) || in_array($column, $allowed_columns, true))) {
				$columns[] = $column;
			}
		}
	}
	if (empty($columns) && !empty($allowed_columns)) {
		$columns = $allowed_columns;
	}

	$chunk_size = 500;
	if (!empty($request['chunk_size'])) {
		$chunk_size = (int)$request['chunk_size'];
	}
	if ($chunk_size < 50) {
		$chunk_size = 50;
	}
	if ($chunk_size > 5000) {
		$chunk_size = 5000;
	}

	$prefix = 'phpog-export';
	if (!empty($policy['filename_prefix'])) {
		$prefix = preg_replace('/[^a-zA-Z0-9_-]/', '', (string)$policy['filename_prefix']);
	}
	$filename = $prefix . '-' . gmdate('Ymd-His') . '.' . $format;
	$content_type = 'text/csv';
	if ($format == 'json') {
		$content_type = 'application/json';
	}

	$result['success'] = true;
	$result['message'] = 'Export stream plan built.';
	$result['data'] = array(
		'format' => $format,
		'filename' => $filename,
		'content_type' => $content_type,
		'columns' => $columns,
		'chunk_size' => $chunk_size,
		'streaming' => true
	);

	return $result;
}