Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix CSV export issue #2215 #2216

Merged
merged 4 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 50 additions & 12 deletions future/includes/rest/class-gv-rest-views-route.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
namespace GV\REST;

use GravityView_Widget_Export_Link;
use GV\Field;
use GV\GF_Form;
use GV\Internal_Source;
use GV\View;
use WP_REST_Request;

/** If this file is called directly, abort. */
Expand Down Expand Up @@ -121,7 +125,7 @@ public function get_item( $request ) {
* Prepare the item for the REST response
*
* @since 2.0
* @param \GV\View $view The view.
* @param View $view The view.
* @param \GV\Entry $entry WordPress representation of the item.
* @param \WP_REST_Request $request Request object.
* @param string $context The context (directory, single)
Expand All @@ -143,7 +147,7 @@ public function prepare_entry_for_response( $view, $entry, \WP_REST_Request $req
* Allow more entry fields that are output in regular REST requests.
*
* @param array $allowed The allowed ones, default by_visible, by_position( "context_*" ), i.e. as set in the view.
* @param \GV\View $view The view.
* @param View $view The view.
* @param \GV\Entry $entry The entry.
* @param \WP_REST_Request $request Request object.
* @param string $context The context (directory, single)
Expand Down Expand Up @@ -173,7 +177,8 @@ function ( $field ) use ( $allowed_field_ids ) {
// remove all links from output.
$field->update_configuration( [ 'show_as_link' => '0' ] );

$source = is_numeric( $field->ID ) ? $view->form : new \GV\Internal_Source();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrcasual This was the cause of the bug - it always used the main form as the source, even when the field belonged to the joined form.

$source = $this->get_source( $field, $view );

$field_id = $field->ID;
$index = null;

Expand All @@ -194,7 +199,7 @@ function ( $field ) use ( $allowed_field_ids ) {
* Filter the key name in the results for JSON output.
*
* @param string $field_id The ID. Should be unique or keys will be gobbled up.
* @param \GV\View $view The view.
* @param View $view The view.
* @param \GV\Entry $entry The entry.
* @param \WP_REST_Request $request Request object.
* @param string $context The context (directory, single)
Expand Down Expand Up @@ -240,6 +245,39 @@ function ( $field ) use ( $allowed_field_ids ) {
return $return;
}

/**
* Gets the source of the field.
*
* @since $ver$
*
* @param Field $field The field.
* @param View $view The view.
*
* @return GF_Form|Internal_Source
*/
protected function get_source( $field, $view ) {
if ( ! is_numeric( $field->ID ) ) {
return new Internal_Source();
}

$form_id = $field->field->formId ?? null;

// If the field's form differs from the main view form, get the form from the joined entries.
if ( $form_id && $view->form->ID != $form_id && ! empty( $view->joins ) ) {
foreach ( $view->joins as $join ) {
if ( isset( $join->join_on->ID ) && $join->join_on->ID == $form_id ) {
return $join->join_on;
}
}

// Edge case where the form cannot be retrieved from the joins.
return GF_Form::by_id( $form_id );
}

// Return the main view form.
return $view->form;
}

/**
* Get entries from a view
*
Expand Down Expand Up @@ -270,7 +308,7 @@ public function get_sub_items( $request ) {
}
}

$view = \GV\View::by_id( $view_id );
$view = View::by_id( $view_id );

if ( null !== $view ) {
$post = $view->get_post();
Expand Down Expand Up @@ -298,7 +336,7 @@ function ( $context ) use ( &$count, &$total ) {
* @since 2.0
* @param bool $insert_meta Add <meta> tags? [Default: true]
* @param int $count The number of entries being rendered
* @param \GV\View $view The view.
* @param View $view The view.
* @param \WP_REST_Request $request Request object.
* @param int $total The number of total entries for the request
*/
Expand Down Expand Up @@ -406,7 +444,7 @@ public function get_sub_item( $request ) {
$entry_id = intval( $url['s_id'] );
$format = \GV\Utils::get( $url, 'format', 'json' );

$view = \GV\View::by_id( $view_id );
$view = View::by_id( $view_id );
$entry = \GV\GF_Entry::by_id( $entry_id );

if ( 'html' === $format ) {
Expand Down Expand Up @@ -434,7 +472,7 @@ public function prepare_view_for_response( $view_post, \WP_REST_Request $request
);
}

$view = \GV\View::from_post( $view_post );
$view = View::from_post( $view_post );

$item = $view->as_data();

Expand Down Expand Up @@ -485,7 +523,7 @@ public function get_item_permissions_check( $request ) {
$view_id = intval( $url['id'] );
}

if ( ! $view = \GV\View::by_id( $view_id ) ) {
if ( ! $view = View::by_id( $view_id ) ) {
return new \WP_Error( 'rest_forbidden', __( 'You are not allowed to access this content.', 'gk-gravityview' ) );
}

Expand Down Expand Up @@ -513,7 +551,7 @@ public function get_item_permissions_check( $request ) {
* Disable rest output. Final chance.
*
* @param bool Enable or not.
* @param \GV\View $view The view.
* @param View $view The view.
*/
if ( ! apply_filters( 'gravityview/view/output/rest', true, $view ) ) {
return new \WP_Error( 'rest_forbidden', __( 'You are not allowed to access this content.', 'gk-gravityview' ) );
Expand All @@ -532,7 +570,7 @@ public function get_sub_item_permissions_check( $request ) {
$view_id = intval( $url['id'] );
$entry_id = intval( $url['s_id'] );

$view = \GV\View::by_id( $view_id );
$view = View::by_id( $view_id );

if ( ! $entry = \GV\GF_Entry::by_id( $entry_id ) ) {
return new \WP_Error( 'rest_forbidden', 'You are not allowed to view this content.', 'gravityview' );
Expand Down Expand Up @@ -580,7 +618,7 @@ public function get_sub_items_permissions_check( $request ) {
$nonce = $request->get_param( '_nonce' );
$view_id = rgar( $params, 'id', 0 );

if ( ! $view = \GV\View::by_id( $view_id ) ) {
if ( ! $view = View::by_id( $view_id ) ) {
return new \WP_Error( 'rest_forbidden', __( 'You are not allowed to access this content.', 'gk-gravityview' ) );
}

Expand Down
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ This release adds a new form notification option for updated entries, resolves f
#### 💻 Developer Updates
* Added `gk/gravityview/view/entries/join-conditions` filter to modify the join conditions applied when retrieving View entries.
* Added `gk/gravityview/template/options` filter to programmatically modify field settings in the View editor.
* Added `gravityview/template/field/csv/tick` filter to programmatically modify the checkbox "check" output in CSV.
* Added `gravityview/row-added` JavaScript event, triggered when a new row is added to a widget or field area.

= 2.31.1 on November 8, 2024 =
Expand Down
68 changes: 53 additions & 15 deletions templates/fields/field-checkbox-csv.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,66 @@
/**
* The default field output template for CSVs.
*
* @global \GV\Template_Context $gravityview
* @since 2.0
* @global Template_Context $gravityview
*/

use GV\Template_Context;
use GV\Utils;

if ( ! isset( $gravityview ) || empty( $gravityview->template ) ) {
gravityview()->log->error( '{file} template loaded without context', array( 'file' => __FILE__ ) );

return;
}

$field_id = $gravityview->field->ID;
$display_value = $gravityview->display_value;
$value = $gravityview->value;
$entry = $gravityview->entry->as_entry();
$field_id = $gravityview->field->ID;
$field = $gravityview->field->field;
$value = $gravityview->value;
$form = $gravityview->view->form->form;
$entry = $gravityview->entry->as_entry();
$field_settings = $gravityview->field->as_configuration();
$display_type = Utils::get( $field_settings, 'choice_display' );
$is_single_input = floor( $field_id ) !== floatval( $field_id );
$output = '';

/**
* The value used to separate multiple values in the CSV export.
*
* @since 2.4.2
*
* @param string The glue. Default: ";" (semicolon)
* @param \GV\Template_Context The context.
*/
$glue = apply_filters( 'gravityview/template/field/csv/glue', ';', $gravityview );
// It's the parent field, not an input
if ( ! $is_single_input ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrcasual This is the same logic as in the field-checkbox-html.php file.

/**
* The value used to separate multiple values in the CSV export.
*
* @since 2.4.2
*
* @param string $glue The glue. Default: ";" (semicolon).
* @param Template_Context $gravityview The context.
*/
$glue = apply_filters( 'gravityview/template/field/csv/glue', ';', $gravityview );
$output = implode( $glue, array_filter( $value ) );
} else {

$field_value = $entry[ $field_id ] ?? '';

switch ( $display_type ) {
case 'label':
$output = gravityview_get_field_label( $form, $field_id, $value );
break;
case 'tick':
default:
if ( $field_value ) {
/**
* Change the output for a checkbox "check" symbol.
*
* @since $ver$
*
* @param string $output Checkbox "check" symbol. Default: "✓".
* @param array $entry Entry data.
* @param GF_Field_Checkbox $field GravityView field.
* @param Template_Context $gravityview The context.
*/
$output = apply_filters( 'gravityview/template/field/csv/tick', '✓', $entry, $field, $gravityview );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zahardev, is there a reason why you didn't use the existing gravityview_field_tick filter?

Copy link
Contributor Author

@zahardev zahardev Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrcasual The gravityview_field_tick filter is used on web pages, and its default value is <span class="dashicons dashicons-yes"></span>. We can't use this value in CSV exports as it won't convert to a tick symbol. That's why I added a new filter specifically for CSV handling. Please let me know if we can somehow improve it or use gravityview_field_tick instead.

Copy link
Contributor

@rafaehlers rafaehlers Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification @zahardev! @mrcasual that explains why DataTables wasn't able to export the ticks (DT strips HTML), and I had to use an emoji in place: https://github.com/GravityKit/DataTables/issues/60#issuecomment-856311493

}
break;
}
}

echo implode( $glue, array_filter( $value ) );
echo $output;