<?php
/**
* Contains Crowdsignal_Forms\Frontend\Blocks\Crowdsignal_Forms_Feedback_block
*
* @package Crowdsignal_Forms\Frontend\Blocks
* @since 1.4.0
*/
namespace Crowdsignal_Forms\Frontend\Blocks;
use Crowdsignal_Forms\Crowdsignal_Forms;
use Crowdsignal_Forms\Frontend\Crowdsignal_Forms_Blocks_Assets;
use Crowdsignal_Forms\Frontend\Crowdsignal_Forms_Block;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Handles Crowdsignal Forms' Feedback block.
*
* @package Crowdsignal_Forms\Frontend\Blocks
* @since 1.4.0
*/
class Crowdsignal_Forms_Feedback_Block extends Crowdsignal_Forms_Block {
/**
* The nonce identifier string for Feedback submission.
*
* @since 1.5.1
* @var string
*/
const NONCE = 'crowdsignal-forms-feedback__submit';
/**
* {@inheritDoc}
*/
public function asset_identifier() {
return 'crowdsignal-forms-feedback';
}
/**
* {@inheritDoc}
*/
public function assets() {
return array(
'config' => '/build/feedback.asset.php',
'script' => '/build/feedback.js',
'style' => '/build/feedback.css',
);
}
/**
* {@inheritDoc}
*/
public function register() {
register_block_type(
'crowdsignal-forms/feedback',
array(
'attributes' => $this->attributes(),
'editor_script' => Crowdsignal_Forms_Blocks_Assets::EDITOR,
'editor_style' => Crowdsignal_Forms_Blocks_Assets::EDITOR,
'render_callback' => array( $this, 'render' ),
)
);
}
/**
* Renders the Feedback dynamic block
*
* @param array $attributes The block's attributes.
* @return string
*/
public function render( $attributes ) {
// Look up surveyId from post_meta if not in attributes but surveyClientId is present.
if ( empty( $attributes['surveyId'] ) && ! empty( $attributes['surveyClientId'] ) ) {
$meta_gateway = Crowdsignal_Forms::instance()->get_post_survey_meta_gateway();
$survey_data = $meta_gateway->get_survey_data_for_client_id( get_the_ID(), $attributes['surveyClientId'] );
if ( ! empty( $survey_data['id'] ) ) {
$attributes['surveyId'] = $survey_data['id'];
}
}
if ( $this->should_hide_block( $attributes ) ) {
return '';
}
wp_enqueue_script( $this->asset_identifier() );
wp_enqueue_style( $this->asset_identifier() );
$attributes['hideBranding'] = $this->should_hide_branding();
$attributes['nonce'] = $this->create_nonce();
// Remove surveyClientId from rendered output - it's only needed server-side
// for post_meta lookup and should not be exposed to the public.
unset( $attributes['surveyClientId'] );
return sprintf(
'<div class="crowdsignal-feedback-wrapper" data-crowdsignal-feedback="%s"></div>',
htmlentities( wp_json_encode( $attributes ) )
);
}
/**
* Determines if the Feedback block should be rendered or not.
*
* @param array $attributes The block's attributes.
* @return bool
*/
private function should_hide_block( $attributes = array() ) {
if (
! empty( $attributes['isWidget'] ) && (
! $this->is_cs_connected() ||
! is_singular()
)
) {
return true;
}
if ( empty( $attributes['surveyId'] ) ) {
return true;
}
if ( isset( $attributes['status'] ) ) {
if ( self::STATUS_TYPE_CLOSED === $attributes['status'] ) {
return true;
} elseif ( self::STATUS_TYPE_SCHEDULED === $attributes['status'] && isset( $attributes['closedAfterDateTime'] ) ) {
try {
$close_date = \DateTime::createFromFormat( 'Y-m-d\TH:i:s+', $attributes['closedAfterDateTime'] );
$timestamp = $close_date->getTimestamp();
} catch ( \Exception $e ) {
return false;
}
if ( time() > $timestamp ) {
return true;
}
}
}
return false;
}
/**
* Returns the attributes definition array for register_block_type
*
* Note: Any changes to the array returned by this function need to be
* duplicated in client/blocks/feedback/attributes.js.
*
* @return array
*/
private function attributes() {
return array(
'backgroundColor' => array(
'type' => 'string',
),
'buttonColor' => array(
'type' => 'string',
),
'buttonTextColor' => array(
'type' => 'string',
),
'emailPlaceholder' => array(
'type' => 'string',
'default' => __( 'Your Email', 'crowdsignal-forms' ),
),
'emailRequired' => array(
'type' => 'boolean',
'default' => false,
),
'feedbackPlaceholder' => array(
'type' => 'string',
'default' => __( 'Please let us know how we can do better…', 'crowdsignal-forms' ),
),
'header' => array(
'type' => 'string',
'default' => __( '👋 Hey there!', 'crowdsignal-forms' ),
),
'hideBranding' => array(
'type' => 'boolean',
'default' => false,
),
'hideTriggerShadow' => array(
'type' => 'boolean',
'default' => false,
),
'submitButtonLabel' => array(
'type' => 'string',
'default' => __( 'Submit', 'crowdsignal-forms' ),
),
'submitText' => array(
'type' => 'string',
'default' => __( 'Thanks for letting us know!', 'crowdsignal-forms' ),
),
'surveyId' => array(
'type' => 'number',
'default' => null,
),
'surveyClientId' => array(
'type' => 'string',
'default' => null,
),
'textColor' => array(
'type' => 'string',
),
'toggleOn' => array(
'type' => 'string',
'default' => 'click',
),
'triggerLabel' => array(
'type' => 'string',
'default' => __( 'Feedback', 'crowdsignal-forms' ),
),
'triggerBackgroundColor' => array(
'type' => 'string',
),
'triggerTextColor' => array(
'type' => 'string',
),
'title' => array(
'type' => 'string',
'default' => null,
),
'x' => array(
'type' => 'string',
'default' => 'left',
),
'y' => array(
'type' => 'string',
'default' => 'bottom',
),
'status' => array(
'type' => 'string',
'default' => 'open', // See: client/blocks/feedback/constants.js.
),
'closedAfterDateTime' => array(
'type' => 'string',
'default' => null,
),
'emailResponses' => array(
'type' => 'boolean',
'default' => true,
),
);
}
/**
* Verifies a nonce based on the NONCE.
* The nonce creation is first attempted through crowdsignal_forms_feedback_nonce filter.
*
* @since 1.5.1
* @param string $nonce
* @return bool
*/
public static function verify_nonce( $nonce ) {
$verifies = apply_filters( 'crowdsignal_forms_feedback_nonce_check', $nonce, self::NONCE );
if ( $verifies === $nonce ) { // returned unfiltered.
$verifies = wp_verify_nonce( $nonce, self::NONCE );
}
return $verifies;
}
/**
* Returns a nonce based on the NONCE.
* The nonce creation is first attempted through crowdsignal_forms_feedback_nonce filter.
*
* @since 1.5.1
* @return string
*/
private function create_nonce() {
$nonce = apply_filters( 'crowdsignal_forms_feedback_nonce', self::NONCE );
if ( self::NONCE === $nonce ) { // returned unfiltered.
$nonce = wp_create_nonce( self::NONCE );
}
return $nonce;
}
}