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

Add a unique key when embedding shortcode #190

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ phpunit.xml.dist export-ignore
README.md export-ignore
strauss.phar export-ignore
build export-ignore
tests

/.circleci export-ignore
/.github export-ignore
Expand Down
15 changes: 15 additions & 0 deletions public/css/gravityexport-lite.css
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,18 @@ fieldset.gk-gravityexport-download-file .gform-settings-panel__content {
border-bottom: 1px solid #ebebf2;
padding-bottom: 10px;
}

.gform-settings-panel .copy-short-code {
display: flex;
justify-content: space-between;
align-items: center;
}

.gform-settings-panel .copy-short-code .input {
flex: 1;
margin-right: 1rem;
}

.gform-settings-panel .copy-short-code .success {
margin-right: 1rem;
}
169 changes: 101 additions & 68 deletions public/js/gravityexport-lite.js
Original file line number Diff line number Diff line change
@@ -1,70 +1,103 @@
var gfexcel_sortable;

(function ($) {
var updateLists = function ($elements) {
$elements.each(function (i, el) {
var $input = $(el).prevAll('input[type=hidden]');
$input.val($(el).sortable('toArray', {attribute: 'data-value'}).join(','));
})
};

gfexcel_sortable = function (elements, connector_class) {
var $elements = $(elements);
var labels_i10n = typeof gravityexport_lite_strings !== 'undefined'
? gravityexport_lite_strings
: {'enable': 'Enable all', 'disable': 'Disable all'}; // Fallback to English

$elements.each(function () {
var $list = $(this);
var send_to = '#' + $list.data('send-to');
var label = send_to.indexOf('enabled') > 0 ? labels_i10n.enable : labels_i10n.disable;
var $move_all_button = $('<button type="button">' + label + '</button>');

$move_all_button
// Add css via JS to hit add-ons.
.css({
background: 'none',
border: 0,
float: 'right',
marginTop: '-30px',
color: '#3e7da6',
cursor: 'pointer'
})
// Move all items to the `send-to` list when clicked.
.on('click', function () {
$list.find('li').appendTo($(send_to));
$elements.sortable('refresh');
updateLists($elements);
});

// Add the button before the list.
$(this).before($move_all_button);
});

$elements.sortable({
connectWith: '.' + connector_class,
update: function () {
updateLists($elements);
}
}).disableSelection();

$elements
.on('click', '.move', function () {
var element = $(this).closest('li');
var send_to = '#' + element.closest('ul').data('send-to');
element.appendTo($(send_to));
setTimeout(function () {
element.addClass('light-up');
setTimeout(function () {
element.removeClass('light-up');
}, 200);
}, 10);
$elements.sortable('refresh');
updateLists($elements);
});
};

$(document).ready(function () {
$("#start_date, #end_date").datepicker({dateFormat: 'yy-mm-dd', changeMonth: true, changeYear: true});
});
})(jQuery);
( function ( $ ) {
var updateLists = function ( $elements ) {
$elements.each( function ( i, el ) {
var $input = $( el ).prevAll( 'input[type=hidden]' );
$input.val( $( el ).sortable( 'toArray', { attribute: 'data-value' } ).join( ',' ) );
} )
};

gfexcel_sortable = function ( elements, connector_class ) {
var $elements = $( elements );
var labels_i10n = typeof gravityexport_lite_strings !== 'undefined'
? gravityexport_lite_strings
: { 'enable': 'Enable all', 'disable': 'Disable all' }; // Fallback to English

$elements.each( function () {
var $list = $( this );
var send_to = '#' + $list.data( 'send-to' );
var label = send_to.indexOf( 'enabled' ) > 0 ? labels_i10n.enable : labels_i10n.disable;
var $move_all_button = $( '<button type="button">' + label + '</button>' );

$move_all_button
// Add css via JS to hit add-ons.
.css( {
background: 'none',
border: 0,
float: 'right',
marginTop: '-30px',
color: '#3e7da6',
cursor: 'pointer'
} )
// Move all items to the `send-to` list when clicked.
.on( 'click', function () {
$list.find( 'li' ).appendTo( $( send_to ) );
$elements.sortable( 'refresh' );
updateLists( $elements );
} );

// Add the button before the list.
$( this ).before( $move_all_button );
} );

$elements.sortable( {
connectWith: '.' + connector_class,
update: function () {
updateLists( $elements );
}
} ).disableSelection();

$elements
.on( 'click', '.move', function () {
var element = $( this ).closest( 'li' );
var send_to = '#' + element.closest( 'ul' ).data( 'send-to' );
element.appendTo( $( send_to ) );
setTimeout( function () {
element.addClass( 'light-up' );
setTimeout( function () {
element.removeClass( 'light-up' );
}, 200 );
}, 10 );
$elements.sortable( 'refresh' );
updateLists( $elements );
} );
};

$( document ).ready( function () {
const $embedShortcodeEl = $( '#embed_code' );
const secret = $embedShortcodeEl.data( 'secret' );

$( '#start_date, #end_date' ).datepicker( { dateFormat: 'yy-mm-dd', changeMonth: true, changeYear: true } );

$( '#file_extension' ).on( 'change', function () {
const shortcode = $embedShortcodeEl.val();
const has_type = shortcode.match( / type=/ );
const regex = has_type ? / type="[^"]*"/ : /]$/;

let type = ` type="${ $( this ).val() }"`;

if ( !has_type ) {
type += ']';
}

$embedShortcodeEl.val( shortcode.replace( regex, type ) );
} );

$( '#has_embed_secret' ).on( 'change', function () {
let embedShortcode = $embedShortcodeEl.val();

if ( !embedShortcode ) {
return;
}

if ( $( this ).is( ':checked' ) ) {
embedShortcode = embedShortcode.replace( /]$/, ` secret="${ secret }"]` );
} else {
embedShortcode = embedShortcode.replace( / secret="[^"]+"/, '' );
}

$embedShortcodeEl.val( embedShortcode );
} );
} );
} )( jQuery );
5 changes: 5 additions & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,11 @@ You can hide a row by adding a hook. Checkout this example:

== Changelog ==

= develop =

* Enhancement: Added security by requiring a secret for embedding the download link shortcode
* Enhancement: Added embed shortcode copy section

= 2.1.0 on September 25, 2023 =

* Bugfix: Data from the old nested form could be exported if the nested form was changed.
Expand Down
5 changes: 4 additions & 1 deletion src/Action/DownloadUrlEnableAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@ public function fire( \GFAddOn $addon, array $form ): void {
return;
}

[ , , $settings ] = $form;
$settings = $form[2] ?? [];

if ( ! empty( $settings['hash'] ?? null ) ) {
// Feed is already enabled.
return;
}

// Enable embed secret by default.
$form[2]['has_embed_secret'] = 1;

parent::fire( $addon, $form );
}
}
39 changes: 39 additions & 0 deletions src/Addon/GravityExportAddon.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use GFExcel\Field\SeparableField;
use GFExcel\GFExcel;
use GFExcel\GFExcelOutput;
use GFExcel\GravityForms\Field\CopyShortcode;
use GFExcel\GravityForms\Field\DownloadFile;
use GFExcel\GravityForms\Field\DownloadUrl;
use GFExcel\GravityForms\Field\SortFields;
Expand Down Expand Up @@ -167,6 +168,7 @@ public function feed_settings_fields(): array {
Fields::register( 'download_file', DownloadFile::class );
Fields::register( 'download_url', DownloadUrl::class );
Fields::register( 'sort_fields', SortFields::class );
Fields::register( 'copy_shortcode', CopyShortcode::class );

$form = $this->get_current_form();

Expand Down Expand Up @@ -212,6 +214,12 @@ public function feed_settings_fields(): array {
'type' => 'download_url',
'assets_dir' => $this->assets_dir,
],
[
'label' => esc_html__( 'Embed shortcode', 'gk-gravityexport-lite' ),
'name' => 'copy_shortcode',
'type' => 'copy_shortcode',
'embed_type' => $this->get_setting( 'file_extension' ),
],
[
'label' => esc_html__( 'Custom Filename', 'gk-gravityexport-lite' ),
'type' => 'text',
Expand Down Expand Up @@ -273,6 +281,19 @@ public function feed_settings_fields(): array {
'collapsible' => true,
'title' => __( 'Security Settings', 'gk-gravityexport-lite' ),
'fields' => [
[
'name' => 'has_embed_secret',
'label' => esc_html__( 'Secure Shortcodes', 'gk-gravityexport-lite' ),
'type' => 'checkbox',
'description' => __( 'A secure shortcode contains a unique <code>secret</code>-attribute which prevents generating the URL for a form without permission.', 'gk-gravityexport-lite' ),
'choices' => [
[
'name' => 'has_embed_secret',
'label' => esc_html__( 'Enable secure embed shortcode', 'gk-gravityexport-lite' ),
'value' => '1',
],
],
],
[
'name' => 'is_secured',
'label' => esc_html__( 'Download Permissions', 'gk-gravityexport-lite' ),
Expand Down Expand Up @@ -1103,4 +1124,22 @@ public function useAdminLabels(): bool {
(bool) $this->get_plugin_setting( 'use_admin_label' )
);
}

/**
* @inheritDoc
* @since $ver$
*/
public function get_current_settings(): array {
$settings = parent::get_current_settings();

$feed = $this->get_feed( $this->get_default_feed_id( rgget( 'id' ) ) );
if ( ! $feed ) {
return $settings;
}

// Prevent hash from being overwritten with an input value.
$settings['hash'] = rgars( $feed, 'meta/hash', $settings['hash'] ?? '' );

return $settings;
}
}
76 changes: 76 additions & 0 deletions src/GravityForms/Field/CopyShortCode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace GFExcel\GravityForms\Field;

use Gravity_Forms\Gravity_Forms\Settings\Fields\HTML;
use GFExcel\Shortcode\DownloadUrl;

/**
* A field that contains the embed shortcode for this feed, with a copy to clipboard button.
* @since $ver$
*/
final class CopyShortcode extends HTML {
/**
* @inheritdoc
* @since $ver$
*/
public $type = 'copy_shortcode';

/**
* @since $ver$
* @var null|string
*/
protected $embed_type;

/**
* @inheritdoc
* @since $ver$
*/
public function scripts(): array {
$script = <<<JS
(function($) {
$( document ).ready(function() {
addClipboard('%s','%s');
});
})(jQuery);
JS;

return [
[
'handle' => 'gk-gravityexport-clipboard-js',
'callback' => function () use ( $script ) {
wp_add_inline_script(
'gk-gravityexport-clipboard-js',
sprintf(
$script,
esc_attr( '#copy-embed-code' ),
esc_attr__( 'The shortcode has been copied to your clipboard.', 'gk-gravityexport-lite' )
)
);
},
'deps' => [ 'jquery', 'wp-a11y', 'wp-i18n', 'clipboard' ],
],
];
}

/**
* @inheritDoc
* @since $ver$
*/
public function markup(): string {
$form_id = (int) rgget( 'id' );
$shortcode = esc_attr( DownloadUrl::generate_embed_short_code( $form_id, $this->embed_type ) );
$secret = DownloadUrl::get_secret( $form_id );
$copy_shortcode = esc_html__( 'Copy Shortcode', 'gk-gravityexport-lite' );

return <<<HTML
<div class="copy-short-code copy-to-clipboard-container">
<div class="input"><input type="text" readonly value="{$shortcode}" id="embed_code" data-secret="{$secret}"></div>
<div class="success hidden" aria-hidden="true">Copied!</div>
<button id="copy-embed-code" type="button" class="button" data-clipboard-target="[id=embed_code]">
<span class="dashicons dashicons-clipboard"></span> {$copy_shortcode}
</button>
</div>
HTML;
}
}
4 changes: 3 additions & 1 deletion src/GravityForms/Field/DownloadUrl.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,9 @@ public function scripts(): array {
return confirm("%s");
});

addClipboard('%s','%s');
if ( 'function' === typeof addClipboard ) {
addClipboard('%s','%s');
}
});

})(jQuery);
Expand Down
2 changes: 1 addition & 1 deletion src/ServiceProvider/AddOnProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use GFExcel\Notification\Manager\NotificationManager;
use GFExcel\Notification\Repository\NotificationRepository;
use GFExcel\Notification\Repository\NotificationRepositoryInterface;
use GFExcel\Shorttag\DownloadUrl;
use GFExcel\Shortcode\DownloadUrl;
use League\Container\Definition\DefinitionInterface;

/**
Expand Down
Loading
Loading