<commit_before><?php

/**
 * @package         Billing
 * @copyright       Copyright (C) 2012-2016 BillRun Technologies Ltd. All rights reserved.
 * @license         GNU Affero General Public License Version 3; see LICENSE.txt
 */

/**
 * Billapi unique get operation
 * Retrieve list of entities while the key or name field is unique
 * This is accounts unique get
 *
 * @package  Billapi
 * @since    5.5
 */
class Models_Action_Export extends Models_Action {

	public function execute() {
		$output = [];
		$query = $this->getExportQuery();
		$entries = $this->getDataToExport($query);
		$mapper = $this->getCsvMapper($entries);
		// add headers
		if (Billrun_Util::getIn($this->options, 'headers', true)) {
			$output[] = $this->getCsvHeaders($mapper);
		}
		// add rows
		foreach ($entries as $entry) {
			$output[] = $this->getRow($entry, $mapper);
		}
		return $output;
	}
	
	protected function getCollection() {
		return $this->request['collection'];
	}

	protected function getFieldsConfig() {
		$collection = $this->getCollection();
		return Billrun_Factory::config()->getConfigValue("{$collection}.fields", []);
	}

	protected function getMapperConfig() {
		$collection = $this->getCollection();
		return Billrun_Factory::config()->getConfigValue("billapi.{$collection}.export.mapper", []);
	}

	protected function getCsvMapper() {
		$fields = $this->getFieldsConfig();
		$config = $this->getMapperConfig();
		$exportable_fields = array_replace_recursive(
			array_column($fields, null, 'field_name'),
			array_column($config, null, 'field_name')
		);
		$exportable_fields = array_filter($exportable_fields, function($field) {
			return Billrun_Util::getIn($field, 'exportable', true);
		});
		$mapper = array_reduce($exportable_fields, function ($acc, $field) {
			$acc[$field['field_name']] = $field;
			return $acc;
		}, []);
		return $mapper;
	}

	protected function getRowValue($data, $path, $params) {
		$defaultValue = Billrun_Util::getIn($params, 'default_value', null);
		$value = Billrun_Util::getIn($data, explode('.', $path), $defaultValue);
		$type = Billrun_Util::getIn($params, 'type', 'string');
		if (empty($value) && $type !== 'boolean' && !in_array($value, [0, '0']) ) {
			return '';
		}
		switch ($type) {
			case 'date':
			case 'datetime':
				return $this->formatDate($value);
			case 'daterange':
				$value = $this->formatDate($value);
				return $this->formatRanges($value);
			case 'range':
				return $this->formatRanges($value);
			case 'percentage':
				return $this->formatPercentage($value);<commit_msg>BRCD-1938 feat(Export) - add support to export complex stucture with arrays<commit_after><?php

/**
 * @package         Billing
 * @copyright       Copyright (C) 2012-2016 BillRun Technologies Ltd. All rights reserved.
 * @license         GNU Affero General Public License Version 3; see LICENSE.txt
 */

/**
 * Billapi unique get operation
 * Retrieve list of entities while the key or name field is unique
 * This is accounts unique get
 *
 * @package  Billapi
 * @since    5.5
 */
class Models_Action_Export extends Models_Action {

	public function execute() {
		$output = [];
		$query = $this->getExportQuery();
		$entries = $this->getDataToExport($query);
		$mapper = $this->getCsvMapper($entries);
		// add headers
		if (Billrun_Util::getIn($this->options, 'headers', true)) {
			$output[] = $this->getCsvHeaders($mapper);
		}
		// add rows
		foreach ($entries as $entry) {
			$output[] = $this->getRow($entry, $mapper);
		}
		return $output;
	}
	
	protected function getCollection() {
		return $this->request['collection'];
	}

	protected function getFieldsConfig() {
		$collection = $this->getCollection();
		return Billrun_Factory::config()->getConfigValue("{$collection}.fields", []);
	}

	protected function getMapperConfig() {
		$collection = $this->getCollection();
		return Billrun_Factory::config()->getConfigValue("billapi.{$collection}.export.mapper", []);
	}

	protected function setCsvOrder($mapper) {
		ksort($mapper); // sort field_name by alphabet and digits
		return $mapper;
	}

	protected function createRecursionMapperKey($config, $configs = []) {
		$max_array_count = 3; // TODO:: TEMP need to find a way how to calculate it from DB
		$path = $config['field_name'];
		$title = isset($config['title']) ? $config['title'] : false;
		$matches = [];
		preg_match('/{[0-9]+}/', $path, $matches);
		if (empty($matches)) {
			$configs[$path] = $config;
			return $configs;
		}
		for ($idx = 0; $idx < $max_array_count; $idx++) {
			$config['field_name'] = str_replace($matches[0], $idx, $path);
			if ($title !== false) {
				$config['title'] = str_replace($matches[0], $idx, $title);
			}
			$configs = $this->createRecursionMapperKey($config, $configs);
		}
		return $configs;
	}

	protected function getCsvMapper() {
		$fields = $this->getFieldsConfig();
		$config = $this->getMapperConfig();
		$exportable_fields = array_replace_recursive(
			array_column($fields, null, 'field_name'),
			array_column($config, null, 'field_name')
		);
		$exportable_fields = array_filter($exportable_fields, function($field) {
			return Billrun_Util::getIn($field, 'exportable', true);
		});
		$mapper = array_reduce($exportable_fields, function ($acc, $field) {
			$acc = array_merge($acc, $this->createRecursionMapperKey($field));
			return $acc;
		}, []);
		$mapper = $this->setCsvOrder($mapper);
		return $mapper;
	}

	protected function getRowValue($data, $path, $params) {
		$defaultValue = Billrun_Util::getIn($params, 'default_value', null);
		$value = Billrun_Util::getIn($data, explode('.', $path), $defaultValue);
		$type = Billrun_Util::getIn($params, 'type', 'string');
		if (empty($value) && $type !== 'boolean' && !in_array($value, [0, '0']) ) {
			return '';
		}
		switch ($type) {
			case 'date':
			case 'datetime':
				return $this->formatDate($value);
			case 'daterange':
				$value = $this->formatDate($value);
				return $this->formatRanges($value);
			case 'range':
				return $this->formatRanges($value);
			case 'percentage':
				return $this->formatPercentage($value);
{'fraction_non_alphanumeric': 0.17107438016528925, 'fraction_numerical': 0.0059504132231404955, 'mean_word_length': 4.5109289617486334, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2363316', 'n_tokens_mistral': 2139, 'n_tokens_neox': 1928, 'n_words': 442}