Skip to content
Snippets Groups Projects
civicrm.shortcodes.php 26.4 KiB
Newer Older
Kevin Cristiano's avatar
Kevin Cristiano committed
<?php
/*
 +--------------------------------------------------------------------+
Kevin Cristiano's avatar
Kevin Cristiano committed
 | Copyright CiviCRM LLC. All rights reserved.                        |
Kevin Cristiano's avatar
Kevin Cristiano committed
 |                                                                    |
Kevin Cristiano's avatar
Kevin Cristiano committed
 | This work is published under the GNU AGPLv3 license with some      |
 | permitted exceptions and without any warranty. For full license    |
 | and copyright information, see https://civicrm.org/licensing       |
Kevin Cristiano's avatar
Kevin Cristiano committed
 +--------------------------------------------------------------------+
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
Kevin Cristiano's avatar
Kevin Cristiano committed

/**
 *
 * @package CRM
Kevin Cristiano's avatar
Kevin Cristiano committed
 * @copyright CiviCRM LLC https://civicrm.org/licensing
Kevin Cristiano's avatar
Kevin Cristiano committed
 *
 */

Kevin Cristiano's avatar
Kevin Cristiano committed
// This file must not accessed directly.
if (!defined('ABSPATH')) {
  exit;
}
Kevin Cristiano's avatar
Kevin Cristiano committed

/**
Kevin Cristiano's avatar
Kevin Cristiano committed
 * Define CiviCRM_For_WordPress_Shortcodes Class.
 *
 * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
 */
class CiviCRM_For_WordPress_Shortcodes {

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @var object
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Plugin object reference.
   * @since 4.6
   * @access public
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public $civi;

Kevin Cristiano's avatar
Kevin Cristiano committed
  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @var array
   * The stored shortcodes.
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
   * @access public
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public $shortcodes = [];
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @var array
   * The array of rendered shortcode markup.
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
   * @access public
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public $shortcode_markup = [];
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @var array
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Count multiple passes of do_shortcode in a post.
   * @since 4.6
   * @access public
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public $shortcode_in_post = [];
Kevin Cristiano's avatar
Kevin Cristiano committed

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Instance constructor.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public function __construct() {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Store reference to CiviCRM plugin object.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->civi = civi_wp();

  }

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Register hooks to handle the presence of shortcodes in content.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function register_hooks() {

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Register the CiviCRM shortcode.
    add_shortcode('civicrm', [$this, 'render_single']);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Add CiviCRM core resources when a shortcode is detected in the post content.
    add_action('wp', [$this, 'prerender'], 10, 1);
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Determine if a CiviCRM shortcode is present in any of the posts about to be displayed.
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Callback method for 'wp' hook, always called from WordPress front-end.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @param object $wp The WordPress object, present but not used.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public function prerender($wp) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
     * At this point, all conditional tags are available
Kevin Cristiano's avatar
Kevin Cristiano committed
     * @see https://codex.wordpress.org/Conditional_Tags
Kevin Cristiano's avatar
Kevin Cristiano committed
     */

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Bail if this is a 404.
    if (is_404()) {
      return;
    }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // A counter's useful.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $shortcodes_present = 0;

Kevin Cristiano's avatar
Kevin Cristiano committed
     * Let's loop through the results.
     * This also has the effect of bypassing the logic in:
     * @see https://github.com/civicrm/civicrm-wordpress/pull/36
Kevin Cristiano's avatar
Kevin Cristiano committed
    if (have_posts()) {
      while (have_posts()) {

        the_post();
Kevin Cristiano's avatar
Kevin Cristiano committed

        global $post;

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Check for existence of shortcode in content.
        if (has_shortcode($post->post_content, 'civicrm')) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
          // Get CiviCRM shortcodes in this post.
          $shortcodes_array = $this->get_for_post($post->post_content);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
          // Sanity check.
          if (!empty($shortcodes_array)) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
            // Add it to our property.
Kevin Cristiano's avatar
Kevin Cristiano committed
            $this->shortcodes[$post->ID] = $shortcodes_array;

Kevin Cristiano's avatar
Kevin Cristiano committed
            // Bump shortcode counter.
            $shortcodes_present += count($this->shortcodes[$post->ID]);
Kevin Cristiano's avatar
Kevin Cristiano committed
      }
Kevin Cristiano's avatar
Kevin Cristiano committed
    // Reset loop.
Kevin Cristiano's avatar
Kevin Cristiano committed
    rewind_posts();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Did we get any?
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ($shortcodes_present) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      // We need CiviCRM initialised prior to parsing shortcodes.
      if (!$this->civi->initialize()) {
        return;
      }

Kevin Cristiano's avatar
Kevin Cristiano committed
      // How should we handle multiple shortcodes?
Kevin Cristiano's avatar
Kevin Cristiano committed
      if ($shortcodes_present > 1) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Add CSS resources for front end.
        add_action('wp_enqueue_scripts', [$this->civi, 'front_end_css_load'], 100);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Let's add dummy markup.
        foreach ($this->shortcodes as $post_id => $shortcode_array) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
          // Set flag if there are multple shortcodes in this post.
          $multiple = (count($shortcode_array) > 1) ? 1 : 0;
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
          foreach ($shortcode_array as $shortcode) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
            // Mimic invoke in multiple shortcode context.
            $this->shortcode_markup[$post_id][] = $this->render_multiple($post_id, $shortcode, $multiple);
Kevin Cristiano's avatar
Kevin Cristiano committed
      }
      else {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Add core resources for front end.
        add_action('wp', [$this->civi, 'front_end_page_load'], 100);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
         * Since we have only one shortcode, run the_loop again.
         * The DB query has already been done, so this has no significant impact.
Kevin Cristiano's avatar
Kevin Cristiano committed
        if (have_posts()) {
          while (have_posts()) {

            the_post();
Kevin Cristiano's avatar
Kevin Cristiano committed

            global $post;

Kevin Cristiano's avatar
Kevin Cristiano committed
            // Is this the post?
Kevin Cristiano's avatar
Kevin Cristiano committed
            if (!array_key_exists($post->ID, $this->shortcodes)) {
Kevin Cristiano's avatar
Kevin Cristiano committed
              continue;
            }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
            // The shortcode must be the first item in the shortcodes array.
Kevin Cristiano's avatar
Kevin Cristiano committed
            $shortcode = $this->shortcodes[$post->ID][0];

Kevin Cristiano's avatar
Kevin Cristiano committed
            // Check to see if a shortcode component has been repeated?
Kevin Cristiano's avatar
Kevin Cristiano committed
            $atts = $this->get_atts($shortcode);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
            // Test for hijacking.
            if (isset($atts['hijack']) && $atts['hijack'] == '1') {
              add_filter('civicrm_context', [$this, 'get_context']);
Kevin Cristiano's avatar
Kevin Cristiano committed
            }

Kevin Cristiano's avatar
Kevin Cristiano committed
            // Store corresponding markup.
            $this->shortcode_markup[$post->ID][] = do_shortcode($shortcode);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
            // Test for hijacking.
            if (isset($atts['hijack']) && $atts['hijack'] == '1') {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
              // Ditch the filter.
              remove_filter('civicrm_context', [$this, 'get_context']);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
              // Set title.
Kevin Cristiano's avatar
Kevin Cristiano committed
              global $civicrm_wp_title;
              $post->post_title = $civicrm_wp_title;

Kevin Cristiano's avatar
Kevin Cristiano committed
              // Override page title.
              add_filter('single_post_title', [$this, 'single_page_title'], 50, 2);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
              // Overwrite content.
              add_filter('the_content', [$this, 'get_content']);
Kevin Cristiano's avatar
Kevin Cristiano committed
          }
Kevin Cristiano's avatar
Kevin Cristiano committed
        }

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Reset loop.
Kevin Cristiano's avatar
Kevin Cristiano committed
        rewind_posts();

      }

    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Flag that we have parsed shortcodes.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $this->shortcodes_parsed = TRUE;

Kevin Cristiano's avatar
Kevin Cristiano committed
    /**
     * Broadcast that shortcodes have been parsed.
     *
     * @since 4.6
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    do_action('civicrm_shortcodes_parsed');
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Handles CiviCRM-defined shortcodes.
   *
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @param array $atts Shortcode attributes array.
   * @return string HTML for output.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public function render_single($atts) {

    // Do not parse shortcodes in REST context for PUT, POST and DELETE methods.
    if (defined('REST_REQUEST') && REST_REQUEST && (isset($_PUT) || isset($_POST) || isset($_DELETE))) {
      // Return the original shortcode.
      $shortcode = '[civicrm';
      foreach ($atts as $att => $val) {
        $shortcode .= ' ' . $att . '="' . $val . '"';
      }
      $shortcode .= ']';
      return $shortcode;
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Check if we've already parsed this shortcode.
Kevin Cristiano's avatar
Kevin Cristiano committed
    global $post;
Kevin Cristiano's avatar
Kevin Cristiano committed
    if (is_object($post)) {
      if (!empty($this->shortcode_markup)) {
        if (isset($this->shortcode_markup[$post->ID])) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
          // Set counter flag.
          if (!isset($this->shortcode_in_post[$post->ID])) {
Kevin Cristiano's avatar
Kevin Cristiano committed
            $this->shortcode_in_post[$post->ID] = 0;
Kevin Cristiano's avatar
Kevin Cristiano committed
          }
          else {
Kevin Cristiano's avatar
Kevin Cristiano committed
            $this->shortcode_in_post[$post->ID]++;
          }

Kevin Cristiano's avatar
Kevin Cristiano committed
          // This shortcode must have been rendered.
Kevin Cristiano's avatar
Kevin Cristiano committed
          return $this->shortcode_markup[$post->ID][$this->shortcode_in_post[$post->ID]];

        }
      }
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Preprocess shortcode attributes.
    $args = $this->preprocess_atts($atts);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Sanity check for improperly constructed shortcode.
    if ($args === FALSE) {
      return '<p>' . __('Do not know how to handle this shortcode.', 'civicrm') . '</p>';
Kevin Cristiano's avatar
Kevin Cristiano committed
    // If the shortcode has a path (`q`), fetch content by invoking the civicrm route
    if (!empty($args['q'])) {
      // invoke() requires environment variables to be set.
      foreach ($args as $key => $value) {
        if ($value !== NULL) {
          set_query_var($key, $value);
          $_REQUEST[$key] = $_GET[$key] = $value;
        }
Kevin Cristiano's avatar
Kevin Cristiano committed
      }

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Kick out if not CiviCRM.
      if (!$this->civi->initialize()) {
        return '';
      }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Check permission.
      $argdata = $this->civi->get_request_args();
      if (!$this->civi->users->check_permission($argdata['args'])) {
Kevin Cristiano's avatar
Kevin Cristiano committed
        return $this->civi->users->get_permission_denied();
Kevin Cristiano's avatar
Kevin Cristiano committed
      }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      // CMW: why do we need this? Nothing that follows uses it.
      require_once ABSPATH . WPINC . '/pluggable.php';
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Start buffering.
      ob_start();
      // Now, instead of echoing, shortcode output ends up in buffer.
      $this->civi->invoke();
      // Save the output and flush the buffer.
      $content = ob_get_clean();
    }
    // If there is no path, rely on civicrm_shortcode_get_markup to provide the markup.
    else {
      $content = '<p>' . __('Do not know how to handle this shortcode.', 'civicrm') . '</p>';
      /**
       * Get the markup for "pathless" Shortcodes.
       *
       * This filter allows plugins or CiviCRM Extensions to modify the markup used
       * to display a shortcode that has no CiviCRM route/path. This may be:
       *
       * * Accidental due to an improperly constructed shortcode or
       * * Deliberate because a component may not require a route/path
       *
       * @since 5.37
       *
       * @param str $markup The default markup for an improperly constructed shortcode.
       * @param array $atts The shortcode attributes array.
       * @param array $args The shortcode arguments array.
       * @param str Context flag - value is either 'single' or 'multiple'.
       * @return str The modified shortcode markup.
       */
      $content = apply_filters('civicrm_shortcode_get_markup', $content, $atts, $args, 'single');
    }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    return $content;
  }

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Return a generic display for a shortcode instead of a CiviCRM invocation.
   *
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @param int $post_id The containing WordPress post ID.
   * @param string $shortcode The shortcode being parsed.
   * @param bool $multiple Boolean flag, TRUE if post has multiple shortcodes, FALSE otherwise.
   * @return string $markup Generic markup for multiple instances.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  private function render_multiple($post_id = FALSE, $shortcode = FALSE, $multiple = 0) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get attributes.
    $atts = $this->get_atts($shortcode);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Pre-process shortcode and retrieve args.
    $args = $this->preprocess_atts($atts);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Sanity check for improperly constructed shortcode.
    if ($args === FALSE) {
      return '<p>' . __('Do not know how to handle this shortcode.', 'civicrm') . '</p>';
Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get pathless markup from filter callback
    if (empty($args['q'])) {
      $markup = '<p>' . __('Do not know how to handle this shortcode.', 'civicrm') . '</p>';
      return apply_filters('civicrm_shortcode_get_markup', $markup, $atts, $args, 'multiple');
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get data for this shortcode.
    $data = $this->get_data($atts, $args);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Sanity check.
    if ($data === FALSE) {
      return '';
    }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Did we get a title?
Kevin Cristiano's avatar
Kevin Cristiano committed
    $title = __('Content via CiviCRM', 'civicrm');
    if (!empty($data['title'])) {
      $title = $data['title'];
    }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Init title flag.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $show_title = TRUE;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Default link.
    $link = get_permalink($post_id);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Default to no class.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $class = '';

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Access CiviCRM config object.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $config = CRM_Core_Config::singleton();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Do we have multiple shortcodes?
Kevin Cristiano's avatar
Kevin Cristiano committed
    if ($multiple != 0) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      $links = [];
      foreach ($args as $var => $arg) {
        if (!empty($arg) && $var != 'q') {
Kevin Cristiano's avatar
Kevin Cristiano committed
          $links[] = $var . '=' . $arg;
        }
      }
Kevin Cristiano's avatar
Kevin Cristiano committed
      $query = implode('&', $links);
Kevin Cristiano's avatar
Kevin Cristiano committed

      // $absolute, $frontend, $forceBackend
      $base_url = $this->civi->get_base_url(TRUE, FALSE, FALSE);

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Init query parts.
      $queryParts = [];
Kevin Cristiano's avatar
Kevin Cristiano committed
      // When not using Clean URLs.
Kevin Cristiano's avatar
Kevin Cristiano committed
      if (!$config->cleanURL) {

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Construct query parts.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $queryParts[] = 'civiwp=CiviCRM';
Kevin Cristiano's avatar
Kevin Cristiano committed
        if (isset($args['q'])) {
          $queryParts[] = 'q=' . $args['q'];
        }
        if (isset($query)) {
          $queryParts[] = $query;
        }

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Construct link.
        $link = trailingslashit($base_url) . '?' . implode('&', $queryParts);
Kevin Cristiano's avatar
Kevin Cristiano committed
      }
Kevin Cristiano's avatar
Kevin Cristiano committed
      else {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Clean URLs.
Kevin Cristiano's avatar
Kevin Cristiano committed
        if (isset($args['q'])) {
Kevin Cristiano's avatar
Kevin Cristiano committed
          $base_url = trailingslashit($base_url) . str_replace('civicrm/', '', $args['q']) . '/';
Kevin Cristiano's avatar
Kevin Cristiano committed
        }
        if (isset($query)) {
          $queryParts[] = $query;
        }
        $link = $base_url . '?' . implode('&', $queryParts);

      }
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Add a class for styling purposes.
Kevin Cristiano's avatar
Kevin Cristiano committed
      $class = ' civicrm-shortcode-multiple';

    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Test for hijacking.
    if (!$multiple) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      if (isset($atts['hijack']) && $atts['hijack'] == '1') {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Add title to array.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $this->post_titles[$post_id] = $data['title'];

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Override title.
        add_filter('the_title', [$this, 'get_title'], 100, 2);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Overwrite content.
        add_filter('the_content', [$this, 'get_content']);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Don't show title.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $show_title = FALSE;

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Add a class for styling purposes.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $class = ' civicrm-shortcode-single';

      }

    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Set some template variables.
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Description.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $description = FALSE;
Kevin Cristiano's avatar
Kevin Cristiano committed
    if (isset($data['text']) && !empty($data['text'])) {
Kevin Cristiano's avatar
Kevin Cristiano committed
      $description = $data['text'];
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Provide an enticing link.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $more_link = sprintf(
      '<a href="%s">%s</a>',
      $link,
Kevin Cristiano's avatar
Kevin Cristiano committed

      /**
       * Filter the CiviCRM shortcode more link text.
       *
       * @since 4.6
       *
       * @param str The existing shortcode more link text.
       * @return str The modified shortcode more link text.
       */
Kevin Cristiano's avatar
Kevin Cristiano committed
      apply_filters('civicrm_shortcode_more_link', __('Find out more...', 'civicrm'))
Kevin Cristiano's avatar
Kevin Cristiano committed
    );

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Assume CiviCRM footer is not enabled.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $empowered_enabled = FALSE;
    $footer = '';

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Test config object for setting.
    if ($config->empoweredBy == 1) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Footer enabled - define it.
      $civi = __('CiviCRM.org - Growing and Sustaining Relationships', 'civicrm');
      $logo = '<div class="empowered-by-logo"><span>' . __('CiviCRM', 'civicrm') . '</span></div>';
      $civi_link = '<a href="https://civicrm.org/" title="' . $civi . '" target="_blank" class="empowered-by-link">' . $logo . '</a>';
      $empowered = sprintf(__('Empowered by %s', 'civicrm'), $civi_link);
Kevin Cristiano's avatar
Kevin Cristiano committed

      /**
       * Filter the CiviCRM shortcode footer text.
       *
       * @since 4.6
       *
       * @param str $empowered The existing shortcode footer.
       * @return str $empowered The modified shortcode footer.
       */
Kevin Cristiano's avatar
Kevin Cristiano committed
      $footer = apply_filters('civicrm_shortcode_footer', $empowered);
Kevin Cristiano's avatar
Kevin Cristiano committed

      $empowered_enabled = TRUE;

    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Start buffering.
Kevin Cristiano's avatar
Kevin Cristiano committed
    ob_start();

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Include template.
    include CIVICRM_PLUGIN_DIR . 'assets/templates/civicrm.shortcode.php';
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Save the output and flush the buffer.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $markup = ob_get_clean();

Kevin Cristiano's avatar
Kevin Cristiano committed
    /**
     * Filter the computed CiviCRM shortcode markup.
     *
     * @since 4.6
     *
     * @param str $markup The computed shortcode markup.
     * @param int $post_id The numeric ID of the WordPress post.
     * @param string $shortcode The shortcode being parsed.
     * @return str $markup The modified shortcode markup.
     */
Kevin Cristiano's avatar
Kevin Cristiano committed
    return apply_filters('civicrm_shortcode_render_multiple', $markup, $post_id, $shortcode);
Kevin Cristiano's avatar
Kevin Cristiano committed
   * In order to hijack the page, we need to override the context.
   *
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @return string The overridden context code.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
  public function get_context() {
    return 'nonpage';
  }

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * In order to hijack the page, we need to override the content.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
   *
   * @return string The overridden content.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public function get_content($content) {
Kevin Cristiano's avatar
Kevin Cristiano committed

    global $post;

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Is this the post?
Kevin Cristiano's avatar
Kevin Cristiano committed
    if (!array_key_exists($post->ID, $this->shortcode_markup)) {
Kevin Cristiano's avatar
Kevin Cristiano committed
      return $content;
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Bail if it has multiple shortcodes.
    if (count($this->shortcode_markup[$post->ID]) > 1) {
Kevin Cristiano's avatar
Kevin Cristiano committed
      return $content;
    }

    return $this->shortcode_markup[$post->ID][0];

  }

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * In order to hijack the page, we need to override the title.
   *
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @param string $title The existing title.
   * @param int $post_id The numeric ID of the WordPress post.
   * @return string $title The overridden title.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public function get_title($title, $post_id) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Is this the post?
Kevin Cristiano's avatar
Kevin Cristiano committed
    if (!array_key_exists($post_id, $this->shortcode_markup)) {
Kevin Cristiano's avatar
Kevin Cristiano committed
      return $title;
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Bail if it has multiple shortcodes.
    if (count($this->shortcode_markup[$post_id]) > 1) {
Kevin Cristiano's avatar
Kevin Cristiano committed
      return $title;
    }

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Shortcodes may or may not override title.
    if (array_key_exists($post_id, $this->post_titles)) {
Kevin Cristiano's avatar
Kevin Cristiano committed
      $title = $this->post_titles[$post_id];
    }

    return $title;

  }

Kevin Cristiano's avatar
Kevin Cristiano committed
  /**
   * Override a WordPress page title with the CiviCRM entity title.
   *
   * Callback method for 'single_page_title' hook, always called from WordPress
   * front-end.
   *
   * @since 4.6
   * @since 5.33 Moved to this class.
   *
   * @param string $post_title The title of the WordPress page or post.
   * @param object $post The WordPress post object the title applies to.
   * @return string $civicrm_wp_title The title of the CiviCRM entity.
   */
  public function single_page_title($post_title, $post) {

    // Sanity check and override.
    global $civicrm_wp_title;
    if (!empty($civicrm_wp_title)) {
      return $civicrm_wp_title;
    }

    // Fallback
    return $post_title;

  }
Kevin Cristiano's avatar
Kevin Cristiano committed

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Detect and return CiviCRM shortcodes in post content.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
   *
   * @param str $content The content to parse.
   * @return array $shortcodes Array of shortcodes.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  private function get_for_post($content) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Init return array.
    $shortcodes = [];
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Attempt to discover all instances of the shortcode.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $pattern = get_shortcode_regex();

    if (
Kevin Cristiano's avatar
Kevin Cristiano committed
      preg_match_all('/' . $pattern . '/s', $content, $matches)
      && array_key_exists(2, $matches)
      && in_array('civicrm', $matches[2])
    ) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      // Get keys for our shortcode.
      $keys = array_keys($matches[2], 'civicrm');
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
      foreach ($keys as $key) {
Kevin Cristiano's avatar
Kevin Cristiano committed
        $shortcodes[] = $matches[0][$key];
      }

    }

    return $shortcodes;

  }

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Return attributes for a given CiviCRM shortcode.
   *
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @param $shortcode The shortcode to parse.
   * @return array $shortcode_atts Array of shortcode attributes.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  private function get_atts($shortcode) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Strip all but attributes definitions.
    $text = str_replace('[civicrm ', '', $shortcode);
    $text = str_replace(']', '', $text);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Extract attributes.
    $shortcode_atts = shortcode_parse_atts($text);
Kevin Cristiano's avatar
Kevin Cristiano committed

    return $shortcode_atts;

  }

  /**
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Preprocess CiviCRM-defined shortcodes.
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @since 4.6
   *
   * @param array $atts Shortcode attributes array.
   * @return array $args Shortcode arguments array.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public function preprocess_atts($atts) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    $defaults = [
Kevin Cristiano's avatar
Kevin Cristiano committed
      'component' => 'contribution',
      'action' => NULL,
      'mode' => NULL,
      'id' => NULL,
      'cid' => NULL,
      'gid' => NULL,
      'cs' => NULL,
      'force' => NULL,
Kevin Cristiano's avatar
Kevin Cristiano committed
    ];
Kevin Cristiano's avatar
Kevin Cristiano committed
    // Parse Shortcode attributes.
    $shortcode_atts = shortcode_atts($defaults, $atts, 'civicrm');
    extract($shortcode_atts);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    $args = [
Kevin Cristiano's avatar
Kevin Cristiano committed
      'reset' => 1,
      'id'    => $id,
      'force' => $force,
Kevin Cristiano's avatar
Kevin Cristiano committed
    ];
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Construct args for known components.
    switch ($component) {
Kevin Cristiano's avatar
Kevin Cristiano committed

      case 'contribution':

Kevin Cristiano's avatar
Kevin Cristiano committed
        if ($mode == 'preview' || $mode == 'test') {
Kevin Cristiano's avatar
Kevin Cristiano committed
          $args['action'] = 'preview';
        }
Kevin Cristiano's avatar
Kevin Cristiano committed

        switch ($action) {
          case 'transact':
            $args['q'] = 'civicrm/contribute/transact';
            break;

          case 'setup':
            $args['q'] = 'civicrm/contribute/campaign';
            $args['action'] = 'add';
            $args['component'] = 'contribute';
            unset($args['id']);
            $args['pageId'] = $id;
            break;

          default:
            $args['q'] = 'civicrm/contribute/transact';
            break;
        }
Kevin Cristiano's avatar
Kevin Cristiano committed
        break;

Kevin Cristiano's avatar
Kevin Cristiano committed
      case 'pcp':

Kevin Cristiano's avatar
Kevin Cristiano committed
        if ($mode == 'preview' || $mode == 'test') {
Kevin Cristiano's avatar
Kevin Cristiano committed
          $args['action'] = 'preview';
        }
Kevin Cristiano's avatar
Kevin Cristiano committed

        switch ($action) {
          case 'transact':
            $args['q'] = 'civicrm/contribute/transact';
            $args['pcpId'] = $args['id'];
            $args['id'] = civicrm_api3('Pcp', 'getvalue', [
              'return' => 'page_id',
              'id' => $args['pcpId'],
            ]);
            break;

          case 'info':
          default:
            $args['q'] = 'civicrm/pcp/info';
            break;
        }
Kevin Cristiano's avatar
Kevin Cristiano committed
        break;

Kevin Cristiano's avatar
Kevin Cristiano committed
      case 'event':

Kevin Cristiano's avatar
Kevin Cristiano committed
        switch ($action) {
Kevin Cristiano's avatar
Kevin Cristiano committed
          case 'register':
            $args['q'] = 'civicrm/event/register';
Kevin Cristiano's avatar
Kevin Cristiano committed
            if ($mode == 'preview' || $mode == 'test') {
Kevin Cristiano's avatar
Kevin Cristiano committed
              $args['action'] = 'preview';
            }
            break;

          case 'info':
            $args['q'] = 'civicrm/event/info';
            break;

          default:
Kevin Cristiano's avatar
Kevin Cristiano committed
            return FALSE;
Kevin Cristiano's avatar
Kevin Cristiano committed
        }
        break;

      case 'user-dashboard':

        $args['q'] = 'civicrm/user';
Kevin Cristiano's avatar
Kevin Cristiano committed
        unset($args['id']);
Kevin Cristiano's avatar
Kevin Cristiano committed
        break;

      case 'profile':

        if ($mode == 'edit') {
          $args['q'] = 'civicrm/profile/edit';
        }
        elseif ($mode == 'view') {
          $args['q'] = 'civicrm/profile/view';
        }
        elseif ($mode == 'search') {
          $args['q'] = 'civicrm/profile';
        }
Kevin Cristiano's avatar
Kevin Cristiano committed
        elseif ($mode == 'map') {
          $args['q'] = 'civicrm/profile/map';
          $args['map'] = 1;
        }
Kevin Cristiano's avatar
Kevin Cristiano committed
        else {
          $args['q'] = 'civicrm/profile/create';
        }
        $args['gid'] = $gid;
        break;

      case 'petition':

        $args['q'] = 'civicrm/petition/sign';
        $args['sid'] = $args['id'];
        unset($args['id']);
        break;

    }

    /**
     * Filter the CiviCRM shortcode arguments.
     *
Kevin Cristiano's avatar
Kevin Cristiano committed
     * This filter allows plugins or CiviCRM Extensions to modify the attributes
     * that the 'civicrm' shortcode allows. Injected attributes and their values
     * will also become available in the $_REQUEST and $_GET arrays.
     *
Kevin Cristiano's avatar
Kevin Cristiano committed
     * @since 4.7.28
     *
     * @param array $args Existing shortcode arguments.
     * @param array $shortcode_atts Shortcode attributes.
     * @return array $args Modified shortcode arguments.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $args = apply_filters('civicrm_shortcode_preprocess_atts', $args, $shortcode_atts);
Kevin Cristiano's avatar
Kevin Cristiano committed

    return $args;
Kevin Cristiano's avatar
Kevin Cristiano committed
   * Post-process CiviCRM-defined shortcodes.
   *
   * @since 4.6
Kevin Cristiano's avatar
Kevin Cristiano committed
   *
Kevin Cristiano's avatar
Kevin Cristiano committed
   * @param array $atts Shortcode attributes array.
   * @param array $args Shortcode arguments array.
   * @return array|bool $data The array data used to build the shortcode markup, or false on failure.
Kevin Cristiano's avatar
Kevin Cristiano committed
   */
Kevin Cristiano's avatar
Kevin Cristiano committed
  public function get_data($atts, $args) {
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Init return array.
    $data = [];
Kevin Cristiano's avatar
Kevin Cristiano committed

    if (!$this->civi->initialize()) {
      return FALSE;
    }

    /**
     * Filter the base CiviCRM API parameters.
     *
Kevin Cristiano's avatar
Kevin Cristiano committed
     * This filter allows plugins or CiviCRM Extensions to modify the API call
     * when there are multiple shortcodes being rendered.
Kevin Cristiano's avatar
Kevin Cristiano committed
     * @since 4.7.28
     *
     * @param array $params Existing API params.
     * @param array $atts Shortcode attributes array.
     * @param array $args Shortcode arguments array.
     * @return array $params Modified API params.
Kevin Cristiano's avatar
Kevin Cristiano committed
    $params = apply_filters('civicrm_shortcode_api_params', [
Kevin Cristiano's avatar
Kevin Cristiano committed
      'version' => 3,
      'sequential' => '1',
Kevin Cristiano's avatar
Kevin Cristiano committed
    ], $atts, $args);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
    // Get the CiviCRM entity via the API.
    switch ($atts['component']) {
Kevin Cristiano's avatar
Kevin Cristiano committed

      case 'contribution':

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Add Contribution Page ID.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $params['id'] = $args['id'];

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Call API.
        $civi_entity = civicrm_api('contribution_page', 'getsingle', $params);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set title.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $data['title'] = $civi_entity['title'];

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set text, if present.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $data['text'] = '';
Kevin Cristiano's avatar
Kevin Cristiano committed
        if (isset($civi_entity['intro_text'])) {
Kevin Cristiano's avatar
Kevin Cristiano committed
          $data['text'] = $civi_entity['intro_text'];
        }

        break;

      case 'event':

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Add Event ID.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $params['id'] = $args['id'];

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Call API.
        $civi_entity = civicrm_api('event', 'getsingle', $params);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set title.
        switch ($atts['action']) {
Kevin Cristiano's avatar
Kevin Cristiano committed
          case 'register':
            $data['title'] = sprintf(
Kevin Cristiano's avatar
Kevin Cristiano committed
              __('Register for %s', 'civicrm'),
Kevin Cristiano's avatar
Kevin Cristiano committed
              $civi_entity['title']
            );
            break;

          case 'info':
          default:
            $data['title'] = $civi_entity['title'];
            break;
        }

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set text, if present.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $data['text'] = '';
Kevin Cristiano's avatar
Kevin Cristiano committed
        if (isset($civi_entity['summary'])) {
Kevin Cristiano's avatar
Kevin Cristiano committed
          $data['text'] = $civi_entity['summary'];
        }
        if (
Kevin Cristiano's avatar
Kevin Cristiano committed
          // Summary is not present or is empty.
          (!isset($civi_entity['summary']) || empty($civi_entity['summary']))
          &&
          // We do have a description.
          isset($civi_entity['description']) && !empty($civi_entity['description'])
Kevin Cristiano's avatar
Kevin Cristiano committed
        ) {
Kevin Cristiano's avatar
Kevin Cristiano committed
          // Override with description.
Kevin Cristiano's avatar
Kevin Cristiano committed
          $data['text'] = $civi_entity['description'];
        }

        break;

      case 'user-dashboard':

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set title.
        $data['title'] = __('Dashboard', 'civicrm');
Kevin Cristiano's avatar
Kevin Cristiano committed
        break;

      case 'profile':

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Add Profile ID.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $params['id'] = $args['gid'];

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Call API.
        $civi_entity = civicrm_api('uf_group', 'getsingle', $params);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set title.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $data['title'] = $civi_entity['title'];

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set text to empty.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $data['text'] = '';
        break;

      case 'petition':

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Add Petition ID.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $params['id'] = $atts['id'];

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Call API.
        $civi_entity = civicrm_api('survey', 'getsingle', $params);
Kevin Cristiano's avatar
Kevin Cristiano committed

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set title.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $data['title'] = $civi_entity['title'];

Kevin Cristiano's avatar
Kevin Cristiano committed
        // Set text, if present.
Kevin Cristiano's avatar
Kevin Cristiano committed
        $data['text'] = '';
Kevin Cristiano's avatar
Kevin Cristiano committed
        if (isset($civi_entity['instructions'])) {
Kevin Cristiano's avatar
Kevin Cristiano committed
          $data['text'] = $civi_entity['instructions'];
        }

        break;

      default:
Kevin Cristiano's avatar
Kevin Cristiano committed
        // Do we need to protect against malformed shortcodes?
    /**
     * Filter the CiviCRM shortcode data array.
     *
Kevin Cristiano's avatar
Kevin Cristiano committed
     * This filter allows plugins or CiviCRM Extensions to modify the data used
     * to display the shortcode when there are multiple shortcodes being rendered.
Kevin Cristiano's avatar
Kevin Cristiano committed
     * @since 4.7.28
     *
Kevin Cristiano's avatar
Kevin Cristiano committed
     * @param array $data The existing shortcode data.
     * @param array $atts Shortcode attributes array.
     * @param array $args Shortcode arguments array.
     * @return array $data The modified shortcode data.
Kevin Cristiano's avatar
Kevin Cristiano committed
    return apply_filters('civicrm_shortcode_get_data', $data, $atts, $args);
Kevin Cristiano's avatar
Kevin Cristiano committed
}