<?php
/**
 * @file class-gravityview-field-workflow_step.php
 * @since 1.17.2
 * @package GravityView
 * @subpackage includes\fields
 */

class GravityView_Field_Workflow_Step extends GravityView_Field {

	var $name = 'workflow_step';

	var $group = 'meta';

	public function __construct() {
		$this->label = esc_html__( 'Workflow Step', 'gravityview' );
		$this->default_search_label = $this->label;
		
		$this->add_hooks();
		
		parent::__construct();
	}
	
	function add_hooks() {

		add_filter( 'gravityview_search_field_label', array( $this, 'modify_gravityview_search_field_step_label' ), 10, 3 );

		add_filter( 'gravityview_widget_search_filters', array( $this, 'modify_frontend_search_fields' ), 10, 3 );

		add_filter( 'gravityview_field_entry_value_workflow_step', array( $this, 'modify_entry_value_workflow_step' ), 10, 4 );
	}

	/**
	 * Get the value of the Workflow Step based on the `workflow_step` entry meta int value
	 *
	 * @uses Gravity_Flow_API::get_current_step
	 *
	 * @param string $output HTML value output
	 * @param array  $entry The GF entry array
	 * @param  array $field_settings Settings for the particular GV field
	 * @param array $field Current field being displayed
	 *
	 * @since 1.17
	 *
	 * @return string If Gravity Flow not found, or entry not processed yet, returns initial value. Otherwise, returns name of workflow step.
	 */
	function modify_entry_value_workflow_step( $output, $entry, $field_settings, $field ) {

		// If not set, the entry hasn't started a workflow
		$has_workflow_step = isset( $entry['workflow_step'] );

		if( $has_workflow_step ) {

			$GFlow = new Gravity_Flow_API( $entry['form_id'] );

			if ( $current_step = $GFlow->get_current_step( $entry ) ) {
				$output = esc_html( $current_step->get_name() );
			} else {
				$output = esc_html__( 'Workflow Complete', 'gravityview' );
			}

			unset( $GFlow );
		}

		return $output;
	}

	/**
	 * Get the Workflow Step ID from a search field key
	 *
	 * @param string $key Search field key, in the following format: `workflow_step_status_[number]`
	 *
	 * @return bool|int The ID of the workflow step. False if not a workflow step field key.
	 */
	private function get_step_id_from_key( $key ) {

		$workflow_step_id = false;

		preg_match( '/workflow_step_status_(\d+)/', $key, $matches );

		if ( ! empty( $matches ) ) {
			$workflow_step_id = intval( $matches[1] );
		}

		return $workflow_step_id;
	}

	/**
	 * @since 1.17.3
	 *
	 * @param string $label Existing label text, sanitized.
	 * @param null|GF_Field $gf_field If search field is connected to a Gravity Forms field, the field object.
	 * @param array $field Array with the following keys: `field` ID of the meta key or field ID to be searched, `input` the type of search input to be shown, `label` the existing label. Same as $label parameter.
	 *
	 * @return string If showing a search field for a Step, show the step label.
	 */
	function modify_gravityview_search_field_step_label( $label = '', $gf_field = null, $field = array() ) {

		$return = $label;

		if ( '' === $label && $workflow_step_id = $this->get_step_id_from_key( $field['field'] ) ) {

			$step = $this->get_workflow_step( $workflow_step_id );

			$return = esc_html( $step->get_label() );
		}

		return $return;
	}

	/**
	 * Get a Gravity_Flow_Step object from the step ID
	 *
	 * @since 1.17.3
	 *
	 * @uses GravityView_View::getFormId() to get the current form being searched
	 * @uses Gravity_Flow_API::get_step()
	 *
	 * @param int $workflow_step_id ID of the step
	 *
	 * @return bool|Gravity_Flow_Step
	 */
	function get_workflow_step( $workflow_step_id = 0 ) {

		$form_id = GravityView_View::getInstance()->getFormId();

		$GFlow = new Gravity_Flow_API( $form_id );

		$workflow_step = $GFlow->get_step( $workflow_step_id );

		if( ! $GFlow || ! $workflow_step ) {
			return false;
		}

		return $workflow_step;
	}

	/**
	 * Set the search field choices to the Steps available for the current form
	 *
	 * @since 1.17.3
	 *
	 * @param array $search_fields
	 * @param GravityView_Widget_Search $widget
	 * @param array $widget_args
	 *
	 * @return array
	 */
	function modify_frontend_search_fields( $search_fields = array(), GravityView_Widget_Search $widget, $widget_args = array() ) {
		
		foreach ( $search_fields as & $search_field ) {

			if ( $this->name === $search_field['key'] ) {

				$form_id = GravityView_View::getInstance()->getFormId();

				$workflow_steps = gravity_flow()->get_steps( $form_id );

				$choices = array();

				foreach ( $workflow_steps as $step ) {
					$choices[] = array(
						'text'   => $step->get_name(),
						'value'   => $step->get_id(),
					);
				}

				$search_field['choices'] = $choices;
			}

			// Workflow Step Statuses
			else if ( $workflow_step_id = $this->get_step_id_from_key( $search_field['key'] ) ) {

				$status_key = sprintf( 'workflow_step_status_%d', $workflow_step_id );

				$search_field['choices'] = GravityView_Plugin_Hooks_Gravity_Flow::get_status_options( null, $status_key );
			}
		}
		
		return $search_fields;
	}

}

new GravityView_Field_Workflow_Step;
