Skip to content
Snippets Groups Projects
civicrm.shortcodes.php 29.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * 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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * 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
      /**
       * @var array
       * Simple flag to note that Shortcode parsing has occurred.
       * @since 4.6
       * @access public
       */
      public $shortcodes_parsed = FALSE;
    
    
    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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        add_shortcode('civicrm', [$this, 'render_single']);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Pre-render CiviCRM content when one or more Shortcodes are detected.
        add_action('wp', [$this, 'prerender'], 20, 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
        // Bail if this is a Favicon request.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if (function_exists('is_favicon') && is_favicon()) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        /**
         * Filter the Shortcode Components that do not invoke CiviCRM.
         *
         * Shortcodes for Components such as Afform do load CiviCRM resources but do
         * not have a CiviCRM path and are not rendered via the `invoke()` method.
         * We can allow multiple instances of these Shortcodes in a single page load.
         *
         * @since 5.56
         *
         * @param array $components The array of Components that do not invoke CiviCRM.
         */
        $components = apply_filters('civicrm_no_invoke_shortcode_components', ['afform']);
    
        // Track the Shortcodes for Components that do and do not invoke CiviCRM.
        $no_invoke_shortcodes = [];
        $total_no_invoke_shortcodes = 0;
        $invoke_shortcodes = [];
        $total_invoke_shortcodes = 0;
    
        // Track the total number of CiviCRM Shortcodes.
        $total_shortcodes = 0;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    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
            /**
             * Filters the Post content.
             *
             * @since 5.75
             *
             * @param string $post_content The Post content.
             * @param WP_Post $post The WordPress Post object.
             */
            $post->post_content = apply_filters('civicrm_prerender_post_content', $post->post_content, $post);
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            // Check for existence of Shortcode in content.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $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 collection of Shortcodes.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                $this->shortcodes[$post->ID] = $shortcodes_array;
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                // Bump Shortcode counter.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                $total_shortcodes += count($this->shortcodes[$post->ID]);
    
                // Check for Components that do not invoke CiviCRM.
                foreach ($shortcodes_array as $key => $shortcode) {
                  $atts = $this->get_atts($shortcode);
                  if (!empty($atts['component']) && in_array($atts['component'], $components)) {
                    $no_invoke_shortcodes[$post->ID][$key] = $shortcode;
                    $total_no_invoke_shortcodes++;
                  }
                  else {
                    $invoke_shortcodes[$post->ID][$key] = $shortcode;
                    $total_invoke_shortcodes++;
                  }
                }
    
    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
        // Bail if there are no Shortcodes.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if ($total_shortcodes === 0) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          return;
        }
    
        // Set context.
        $this->civi->civicrm_context_set('shortcode');
    
    
    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
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if ($total_invoke_shortcodes === 1) {
    
    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.
           */
          if (have_posts()) {
            while (have_posts()) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              the_post();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              global $post;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // Is this the post?
              if (!array_key_exists($post->ID, $invoke_shortcodes)) {
                continue;
              }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // The Shortcode must be the item in the Shortcodes array.
              $shortcode = reset($invoke_shortcodes[$post->ID]);
              $key = key($invoke_shortcodes[$post->ID]);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // Check to see if a Shortcode component has been repeated?
              $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']) && 1 === (int) $atts['hijack']) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                add_filter('civicrm_context', [$this, 'get_context']);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // Store corresponding markup.
              $this->shortcode_markup[$post->ID][$key] = do_shortcode($shortcode);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // Test for hijacking.
    
              if (isset($atts['hijack']) && 1 === (int) $atts['hijack']) {
    
    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.
                global $civicrm_wp_title;
                $post->post_title = $civicrm_wp_title;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    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
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // Reset loop.
          rewind_posts();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // How should we handle multiple non-invoking Shortcodes?
        if ($total_no_invoke_shortcodes > 0) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // Let's render Shortcodes that do not invoke CiviCRM.
          foreach ($no_invoke_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 multiple 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 $key => $shortcode) {
              // Mimic invoke in multiple Shortcode context.
              $this->shortcode_markup[$post_id][$key] = $this->render_multiple($post_id, $shortcode, $multiple);
            }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // How should we handle multiple invoking Shortcodes?
        if ($total_invoke_shortcodes > 1) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // Let's add dummy markup for Shortcodes that invoke CiviCRM.
          foreach ($invoke_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 multiple Shortcodes in this post.
            $multiple = (count($shortcode_array) > 1) ? 1 : 0;
    
            foreach ($shortcode_array as $key => $shortcode) {
              // Mimic invoke in multiple Shortcode context.
              $this->shortcode_markup[$post_id][$key] = $this->render_multiple($post_id, $shortcode, $multiple);
            }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // A single Shortcode and any pathless Shortcodes need CiviCRM resources.
        if ($total_no_invoke_shortcodes > 0 || $total_shortcodes === 1) {
          // Add CiviCRM resources for front end.
          add_action('wp', [$this->civi, 'front_end_page_load'], 100);
        }
    
        // Multiple invoking Shortcodes need the CiviCRM CSS file.
        if ($total_invoke_shortcodes > 1) {
          // 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
        // Flag that we have parsed Shortcodes.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $this->shortcodes_parsed = TRUE;
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        /**
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * Broadcast that Shortcodes have been parsed.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         *
         * @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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
       * @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) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        global $post;
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Do not parse Shortcodes in REST context for PUT, POST and DELETE methods.
    
        // Nonce is not necessary here.
        // phpcs:ignore WordPress.Security.NonceVerification.Missing
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if (defined('REST_REQUEST') && REST_REQUEST && (isset($_PUT) || isset($_POST) || isset($_DELETE))) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // Return the original Shortcode.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $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
        // Get the Shortcode Theme Compatibility setting.
        $theme_mode = $this->civi->admin->get_theme_compatibility_mode();
    
        // Check the chosen theme compatibility scenario.
        if ($theme_mode === 'loop') {
          $theme_check = in_the_loop();
        }
        else {
          $theme_check = ('the_content' === current_filter()) ? TRUE : FALSE;
        }
    
        /**
         * Filters the chosen theme compatibility check.
         *
         * If neither 'loop' nor 'filter' work for your theme, you can implement a custom
         * theme compatibility check using this filter. You will most likely have to dig
         * into how your theme renders content to find out what check to implement.
         *
         * @since 5.80
         *
         * @param bool $theme_check True if the check has passed, false otherwise.
         * @param bool $theme_mode The Shortcode Theme Compatibility setting.
         */
        $theme_check = apply_filters('civicrm_theme_compatibility_mode', $theme_check, $theme_mode);
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        /*
         * Check if we've already rendered this Shortcode by parsing post content in
         * The Loop in `prerender()` above. CiviCRM Shortcodes that are rendered via
         * `do_shortcode('[civicrm ...]')` elsewhere (e.g. in a template) will never
         * have been prerendered and cannot be present in the Shortcode markup array.
         */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if ($theme_check) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          if (is_object($post)) {
            if (!empty($this->shortcode_markup)) {
              if (isset($this->shortcode_markup[$post->ID])) {
    
                // Set counter flag.
                if (!isset($this->shortcode_in_post[$post->ID])) {
                  $this->shortcode_in_post[$post->ID] = 0;
                }
                else {
                  $this->shortcode_in_post[$post->ID]++;
                }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                // This Shortcode must have been rendered.
                return $this->shortcode_markup[$post->ID][$this->shortcode_in_post[$post->ID]];
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Preprocess Shortcode attributes.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $args = $this->preprocess_atts($atts);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Check for pathless Shortcode.
        if (empty($args['q'])) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $content = '<p>' . __('This Shortcode could not be handled. It could be malformed or used incorrectly.', 'civicrm') . '</p>';
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          /**
           * Get the markup for "pathless" Shortcodes.
           *
           * This filter allows plugins or CiviCRM Extensions to modify the markup used
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           * to display a Shortcode that has no CiviCRM route/path. This may be:
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           * * Accidental due to an improperly constructed Shortcode or
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           * * Deliberate because a component may not require a route/path
           *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           * Used internally by:
           *
           * - afform_shortcode_content()
           *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           * @since 5.37
           *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           * @param str $content The default markup for an improperly constructed Shortcode.
           * @param array $atts The Shortcode attributes array.
           * @param array $args The Shortcode arguments array.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           * @param str Context flag - value is either 'single' or 'multiple'.
           */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          return apply_filters('civicrm_shortcode_get_markup', $content, $atts, $args, 'single');
    
        }
    
        // If there are *actual* CiviCRM query vars, let them take priority.
        if (!$this->civi->civicrm_in_wordpress()) {
    
          // Get the Shortcode Mode setting.
          $shortcode_mode = $this->civi->admin->get_shortcode_mode();
    
          /** This filter is documented in includes/civicrm.basepage.php */
          $basepage_mode = (bool) apply_filters('civicrm_force_basepage_mode', FALSE, $post);
    
          // Skip unless in "legacy mode" or "Base Page mode" is forced.
          if ($shortcode_mode !== 'legacy' || !$basepage_mode) {
    
            // 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
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if (!$this->civi->initialize()) {
          return '';
        }
    
        // 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
        }
    
        // 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();
    
    
    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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
       * @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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @param string $shortcode The Shortcode being parsed.
       * @param bool $multiple Boolean flag, TRUE if post has multiple Shortcodes, FALSE otherwise.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $args = $this->preprocess_atts($atts);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Get pathless markup from filter callback.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if (empty($args['q'])) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $markup = '';
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          /** This filter is documented in includes/civicrm-shortcodes.php */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          return apply_filters('civicrm_shortcode_get_markup', $markup, $atts, $args, 'multiple');
        }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Get data for this Shortcode.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $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
        // Do we have multiple Shortcodes?
    
        if ($multiple !== 0) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // Build link to Base Page.
          $path = $args['q'];
          unset($args['q']);
          $link = civicrm_basepage_url($path, $args, TRUE, NULL, FALSE);
    
    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
    
    
          if (isset($atts['hijack']) && 1 === (int) $atts['hijack']) {
    
    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'];
        }
    
    
        /**
         * Filter the CiviCRM Shortcode more link text.
         *
         * @since 4.6
         *
         * @param str The existing Shortcode more link text.
         */
        $link_text = apply_filters('civicrm_shortcode_more_link', __('Find out more...', 'civicrm'));
    
        // Provide an enticing link.
        $more_link = sprintf('<a href="%s">%s</a>', $link, $link_text);
    
    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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if (1 === (int) CRM_Core_Config::singleton()->empoweredBy) {
    
    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>';
    
          /* translators: %s: The link to the CiviCRM website. */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $empowered = sprintf(__('Empowered by %s', 'civicrm'), $civi_link);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           * Filter the CiviCRM Shortcode footer text.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           *
           * @since 4.6
           *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
           * @param str $empowered The existing 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
        /**
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * Filter the computed CiviCRM Shortcode markup.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         *
         * @since 4.6
         *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * @param str $markup The computed Shortcode markup.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * @param int $post_id The numeric ID of the WordPress post.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * @param string $shortcode The Shortcode being parsed.
    
    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
       *
    
       * @param string $content The content.
       * @return string $content 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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        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 = 0) {
    
        // Bail if there is no Post ID.
        if (empty($post_id)) {
          return $title;
        }
    
    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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @since 5.44 Made recursive.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
       * @param str $content The content to parse.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @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)
        ) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // Get keys for our Shortcode.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $keys = array_keys($matches[2], 'civicrm');
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // Add found Shortcodes at this level.
          if (!empty($keys)) {
            foreach ($keys as $key) {
              $shortcodes[] = $matches[0][$key];
            }
          }
    
          // Recurse when nested Shortcodes are found.
          if (!empty($matches[5])) {
            foreach ($matches[5] as $match) {
              if (!empty($match)) {
                $shortcodes_deeper = $this->get_for_post($match);
                $shortcodes = array_merge($shortcodes, $shortcodes_deeper);
              }
            }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Return attributes for a given CiviCRM Shortcode.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
       * @since 4.6
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
       * @param string $shortcode The Shortcode to parse.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @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.
    
        $attributes = shortcode_atts($defaults, $atts, 'civicrm');
    
    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'    => $attributes['id'],
          'force' => $attributes['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 ($attributes['component']) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
          case 'contribution':
    
    
            if ($attributes['mode'] === 'preview' || $attributes['mode'] === 'test') {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $args['action'] = 'preview';
            }
    
            switch ($attributes['action']) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              case 'setup':
                $args['q'] = 'civicrm/contribute/campaign';
                $args['action'] = 'add';
                $args['component'] = 'contribute';
                unset($args['id']);
    
                $args['pageId'] = $attributes['id'];
    
              case 'transact':
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              default:
                $args['q'] = 'civicrm/contribute/transact';
                break;
            }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            break;
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          case 'pcp':
    
    
            if ($attributes['mode'] === 'preview' || $attributes['mode'] === 'test') {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $args['action'] = 'preview';
            }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
            switch ($attributes['action']) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              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':
    
    
            switch ($attributes['action']) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              case 'register':
                $args['q'] = 'civicrm/event/register';
    
                if ($attributes['mode'] === 'preview' || $attributes['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 ($attributes['mode'] === 'edit') {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $args['q'] = 'civicrm/profile/edit';
            }
    
            elseif ($attributes['mode'] === 'view') {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $args['q'] = 'civicrm/profile/view';
            }
    
            elseif ($attributes['mode'] === 'search') {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $args['q'] = 'civicrm/profile';
            }
    
            elseif ($attributes['mode'] === 'map') {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $args['q'] = 'civicrm/profile/map';
              $args['map'] = 1;
            }
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            else {
              $args['q'] = 'civicrm/profile/create';
            }
    
            $args['gid'] = $attributes['gid'];
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            break;
    
          case 'petition':
    
            $args['q'] = 'civicrm/petition/sign';
            $args['sid'] = $args['id'];
            unset($args['id']);
            break;
    
        }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * Filter the CiviCRM Shortcode arguments.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * This filter allows plugins or CiviCRM Extensions to modify the attributes
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * 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
         *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * @param array $args Existing Shortcode arguments.
    
         * @param array $attributes Shortcode attributes.
    
        return apply_filters('civicrm_shortcode_preprocess_atts', $args, $attributes);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Post-process CiviCRM-defined Shortcodes.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
       * @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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * 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.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $params = apply_filters('civicrm_shortcode_api_params', [
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          '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':