civicrm.shortcodes.php 24.7 KB
Newer Older
1 2 3
<?php
/*
 +--------------------------------------------------------------------+
Seamus Lee's avatar
Seamus Lee committed
4
 | CiviCRM version 5                                                  |
5
 +--------------------------------------------------------------------+
6
 | Copyright CiviCRM LLC (c) 2004-2019                                |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
 +--------------------------------------------------------------------+
 | This file is a part of CiviCRM.                                    |
 |                                                                    |
 | CiviCRM is free software; you can copy, modify, and distribute it  |
 | under the terms of the GNU Affero General Public License           |
 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception.   |
 |                                                                    |
 | CiviCRM is distributed in the hope that it will be useful, but     |
 | WITHOUT ANY WARRANTY; without even the implied warranty of         |
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
 | See the GNU Affero General Public License for more details.        |
 |                                                                    |
 | You should have received a copy of the GNU Affero General Public   |
 | License and the CiviCRM Licensing Exception along                  |
 | with this program; if not, contact CiviCRM LLC                     |
 | at info[AT]civicrm[DOT]org. If you have questions about the        |
 | GNU Affero General Public License or the licensing of CiviCRM,     |
 | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
 +--------------------------------------------------------------------+
*/

/**
 *
 * @package CRM
31
 * @copyright CiviCRM LLC (c) 2004-2019
32 33 34 35
 *
 */


36
// This file must not accessed directly
37 38 39 40
if ( ! defined( 'ABSPATH' ) ) exit;


/**
41 42 43
 * Define CiviCRM_For_WordPress_Shortcodes Class.
 *
 * @since 4.6
44 45 46 47
 */
class CiviCRM_For_WordPress_Shortcodes {

  /**
48 49 50 51 52
   * Plugin object reference.
   *
   * @since 4.6
   * @access public
   * @var object $civi The plugin object reference.
53 54
   */
  public $civi;
55

56 57 58 59 60 61 62
  /**
   * Stored shortcodes.
   *
   * @since 4.6
   * @access public
   * @var array $shortcodes The stored shortcodes.
   */
63
  public $shortcodes = array();
64

65 66 67 68 69 70 71
  /**
   * Rendered shortcode markup.
   *
   * @since 4.6
   * @access public
   * @var array $shortcode_markup The array of rendered shortcode markup.
   */
72
  public $shortcode_markup = array();
73

74 75 76 77 78 79 80
  /**
   * Count multiple passes of do_shortcode in a post.
   *
   * @since 4.6
   * @access public
   * @var array $shortcode_in_post Count multiple passes of do_shortcode in a post.
   */
81 82 83 84
  public $shortcode_in_post = array();


  /**
85
   * Instance constructor.
86
   *
87
   * @since 4.6
88 89
   */
  function __construct() {
90

91
    // Store reference to CiviCRM plugin object
92
    $this->civi = civi_wp();
93

94 95 96 97
  }


  /**
98
   * Register hooks to handle the presence of shortcodes in content.
99
   *
100
   * @since 4.6
101 102 103
   */
  public function register_hooks() {

104
    // Register the CiviCRM shortcode
105
    add_shortcode( 'civicrm', array( $this, 'render_single' ) );
106

107
    // Add CiviCRM core resources when a shortcode is detected in the post content
108
    add_action( 'wp', array( $this, 'prerender' ), 10, 1 );
109

110 111 112 113
  }


  /**
114 115 116
   * Determine if a CiviCRM shortcode is present in any of the posts about to be displayed.
   *
   * Callback method for 'wp' hook, always called from WP front-end.
117
   *
118 119 120
   * @since 4.6
   *
   * @param object $wp The WP object, present but not used.
121 122 123
   */
  public function prerender( $wp ) {

124
    /*
125 126 127
     * At this point, all conditional tags are available
     * @see http://codex.wordpress.org/Conditional_Tags
     */
128

129
    // Bail if this is a 404
130
    if ( is_404() ) return;
131

132
    // A counter's useful
133
    $shortcodes_present = 0;
134

135 136 137 138 139
    /*
     * Let's loop through the results
     * This also has the effect of bypassing the logic in
     * https://github.com/civicrm/civicrm-wordpress/pull/36
     */
140 141
    if ( have_posts() ) {
      while ( have_posts() ) : the_post();
142

143
        global $post;
144

145
        // Check for existence of shortcode in content
146
        if ( has_shortcode( $post->post_content, 'civicrm' ) ) {
147

148
          // Get CiviCRM shortcodes in this post
149
          $shortcodes_array = $this->get_for_post( $post->post_content );
150

151
          // Sanity check
152
          if ( !empty( $shortcodes_array ) ) {
153

154
            // Add it to our property
155
            $this->shortcodes[$post->ID] = $shortcodes_array;
156

157
            // Bump shortcode counter
158
            $shortcodes_present += count( $this->shortcodes[$post->ID] );
159

160
          }
161

162
        }
163

164 165
      endwhile;
    }
166

167
    // Reset loop
168
    rewind_posts();
169

170
    // Did we get any?
171
    if ( $shortcodes_present ) {
172

173
      // We need CiviCRM initialised prior to parsing shortcodes
174 175 176 177
      if (!$this->civi->initialize()) {
        return;
      }

178
      // How should we handle multiple shortcodes?
179
      if ( $shortcodes_present > 1 ) {
180

181
        // Add CSS resources for front end
182
        add_action( 'wp_enqueue_scripts', array( $this->civi, 'front_end_css_load' ), 100 );
183

184
        // Let's add dummy markup
185
        foreach( $this->shortcodes AS $post_id => $shortcode_array ) {
186

187
          // Set flag if there are multple shortcodes in this post
188
          $multiple = ( count( $shortcode_array ) > 1 ) ? 1 : 0;
189

190
          foreach( $shortcode_array AS $shortcode ) {
191

192
            // Mimic invoke in multiple shortcode context
193
            $this->shortcode_markup[$post_id][] = $this->render_multiple( $post_id, $shortcode, $multiple );
194

195
          }
196

197
        }
198

199
      } else {
200

201
        // Add core resources for front end
202
        add_action( 'wp', array( $this->civi, 'front_end_page_load' ), 100 );
203

204 205 206 207
        /*
         * Since we have only one shortcode, run the_loop again
         * the DB query has already been done, so this has no significant impact
         */
208 209
        if ( have_posts() ) {
          while ( have_posts() ) : the_post();
210

211
            global $post;
212

213
            // Is this the post?
214 215 216
            if ( ! array_key_exists( $post->ID, $this->shortcodes ) ) {
              continue;
            }
217

218
            // The shortcode must be the first item in the shortcodes array
219
            $shortcode = $this->shortcodes[$post->ID][0];
220

221
            // Check to see if a shortcode component has been repeated?
222
            $atts = $this->get_atts( $shortcode );
223

224
            // Test for hijacking
225 226 227
            if ( isset( $atts['hijack'] ) AND $atts['hijack'] == '1' ) {
              add_filter( 'civicrm_context', array( $this, 'get_context' ) );
            }
228

229
            // Store corresponding markup
230
            $this->shortcode_markup[$post->ID][] = do_shortcode( $shortcode );
231

232
            // Test for hijacking
233
            if ( isset( $atts['hijack'] ) AND $atts['hijack'] == '1' ) {
234

235
              // Ditch the filter
236
              remove_filter( 'civicrm_context', array( $this, 'get_context' ) );
237

238
              // Set title
239 240
              global $civicrm_wp_title;
              $post->post_title = $civicrm_wp_title;
241

242
              // Override page title
243
              add_filter( 'single_post_title', array( $this->civi, 'single_page_title' ), 50, 2 );
244

245
              // Overwrite content
246
              add_filter( 'the_content', array( $this, 'get_content' ) );
247

248
            }
249

250 251
          endwhile;
        }
252

253
        // Reset loop
254
        rewind_posts();
255

256
      }
257

258
    }
259

260
    // Flag that we have parsed shortcodes
261
    $this->shortcodes_parsed = TRUE;
262

263 264 265 266 267
    /**
     * Broadcast that shortcodes have been parsed.
     *
     * @since 4.6
     */
268
    do_action( 'civicrm_shortcodes_parsed' );
269

270 271 272 273
  }


  /**
274 275 276
   * Handles CiviCRM-defined shortcodes.
   *
   * @since 4.6
277
   *
278 279
   * @param array $atts Shortcode attributes array.
   * @return string HTML for output.
280 281
   */
  public function render_single( $atts ) {
282 283 284 285 286 287 288 289 290 291
    // 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;
    }
292

293
    // Check if we've already parsed this shortcode
294 295 296 297
    global $post;
    if ( is_object($post) ) {
      if ( !empty( $this->shortcode_markup ) ) {
        if ( isset( $this->shortcode_markup[$post->ID] ) ) {
298

299
          // Set counter flag
300 301 302 303 304
          if ( ! isset( $this->shortcode_in_post[$post->ID] ) ) {
            $this->shortcode_in_post[$post->ID] = 0;
          } else {
            $this->shortcode_in_post[$post->ID]++;
          }
305

306
          // This shortcode must have been rendered
307
          return $this->shortcode_markup[$post->ID][$this->shortcode_in_post[$post->ID]];
308

309 310 311
        }
      }
    }
312

313
    // Preprocess shortcode attributes
314
    $args = $this->preprocess_atts( $atts );
315

316
    // Sanity check for improperly constructed shortcode
317 318 319 320
    if ( $args === FALSE ) {
      return '<p>' . __( 'Do not know how to handle this shortcode.', 'civicrm' ) . '</p>';
    }

321 322 323
    // invoke() requires environment variables to be set
    foreach ( $args as $key => $value ) {
      if ( $value !== NULL ) {
haystack's avatar
haystack committed
324
        set_query_var($key, $value);
325 326 327 328
        $_REQUEST[$key] = $_GET[$key] = $value;
      }
    }

329
    // Kick out if not CiviCRM
330 331 332 333
    if (!$this->civi->initialize()) {
      return '';
    }

334
    // Check permission
335 336 337 338 339 340 341
    $argdata = $this->civi->get_request_args();
    if ( ! $this->civi->users->check_permission( $argdata['args'] ) ) {
      return $this->civi->users->get_permission_denied();;
    }

    // CMW: why do we need this? Nothing that follows uses it...
    require_once ABSPATH . WPINC . '/pluggable.php';
342

343 344 345
    ob_start(); // Start buffering
    $this->civi->invoke(); // Now, instead of echoing, shortcode output ends up in buffer
    $content = ob_get_clean(); // Save the output and flush the buffer
346 347 348 349 350 351
    return $content;

  }


  /**
352
   * Return a generic display for a shortcode instead of a CiviCRM invocation.
353
   *
354 355 356 357 358 359
   * @since 4.6
   *
   * @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.
360 361
   */
  private function render_multiple( $post_id = FALSE, $shortcode = FALSE, $multiple = 0 ) {
362

363
    // Get attributes
364
    $atts = $this->get_atts( $shortcode );
365

366
    // Pre-process shortcode and retrieve args
367
    $args = $this->preprocess_atts( $atts );
368

369
    // Sanity check for improperly constructed shortcode
370 371 372 373
    if ( $args === FALSE ) {
      return '<p>' . __( 'Do not know how to handle this shortcode.', 'civicrm' ) . '</p>';
    }

374
    // Get data for this shortcode
375
    $data = $this->get_data( $atts, $args );
376

377
    // Sanity check
378
    if ( $data === FALSE ) return '';
379

380
    // Did we get a title?
381 382
    $title = __( 'Content via CiviCRM', 'civicrm' );
    if ( ! empty( $data['title'] ) ) $title = $data['title'];
383

384
    // Init title flag
385
    $show_title = TRUE;
386

387
    // Default link
388
    $link = get_permalink( $post_id );
389

390
    // Default to no class
391
    $class = '';
392

393
    // Access CIvi config object
394
    $config = CRM_Core_Config::singleton();
395

396
    // Do we have multiple shortcodes?
397
    if ( $multiple != 0 ) {
398 399

      $links = array();
400 401 402 403 404 405
      foreach( $args AS $var => $arg ) {
        if ( ! empty( $arg ) AND $var != 'q' ) {
          $links[] = $var . '=' . $arg;
        }
      }
      $query = implode( '&', $links );
406

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

haystack's avatar
haystack committed
410
      // Init query parts
411
      $queryParts = array();
haystack's avatar
haystack committed
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427

      // When not using clean URLs
      if (!$config->cleanURL) {

        // Construct query parts
        $queryParts[] = 'page=CiviCRM';
        if (isset($args['q'])) {
          $queryParts[] = 'q=' . $args['q'];
        }
        if (isset($query)) {
          $queryParts[] = $query;
        }

        // Construct link
        $link = trailingslashit( $base_url ) . '?' . implode('&', $queryParts);

428
      }
haystack's avatar
haystack committed
429
      else {
430

haystack's avatar
haystack committed
431 432 433 434 435 436 437 438 439 440
        // Clean URLs
        if (isset($args['q'])) {
          $base_url = trailingslashit( $base_url ) . str_replace('civicrm/', '', $args['q']) . '/';
        }
        if (isset($query)) {
          $queryParts[] = $query;
        }
        $link = $base_url . '?' . implode('&', $queryParts);

      }
441

442
      // Add a class for styling purposes
443
      $class = ' civicrm-shortcode-multiple';
444

445
    }
446

447
    // Test for hijacking
448
    if ( !$multiple ) {
449

450
      if ( isset( $atts['hijack'] ) AND $atts['hijack'] == '1' ) {
451

452
        // Add title to array
453
        $this->post_titles[$post_id] = $data['title'];
454

455
        // Override title
456
        add_filter( 'the_title', array( $this, 'get_title' ), 100, 2 );
457

458
        // Overwrite content
459
        add_filter( 'the_content', array( $this, 'get_content' ) );
460

461
        // Don't show title
462
        $show_title = FALSE;
463

464
        // Add a class for styling purposes
465
        $class = ' civicrm-shortcode-single';
466

467
      }
468

469
    }
470

471
    // Set some template variables
472

473
    // Description
474
    $description = FALSE;
475
    if ( isset( $data['text'] ) AND ! empty( $data['text'] ) ) {
476
      $description = $data['text'];
477
    }
478

479
    // Provide an enticing link
480
    $more_link = sprintf(
481 482
      '<a href="%s">%s</a>',
      $link,
483 484 485 486 487 488 489 490 491

      /**
       * 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.
       */
492
      apply_filters( 'civicrm_shortcode_more_link', __( 'Find out more...', 'civicrm' ) )
493

494
    );
495

496
    // Assume CiviCRM footer is not enabled
497 498
    $empowered_enabled = FALSE;
    $footer = '';
499

500
    // Test config object for setting
501
    if ( $config->empoweredBy == 1 ) {
502

503
      // Footer enabled - define it
504 505 506 507
      $civi = __( 'CiviCRM.org - Growing and Sustaining Relationships', 'civicrm' );
      $logo = '<div class="empowered-by-logo"><span>' . __( 'CiviCRM', 'civicrm' ) . '</span></div>';
      $civi_link = '<a href="http://civicrm.org/" title="' . $civi . '" target="_blank" class="empowered-by-link">' . $logo . '</a>';
      $empowered = sprintf( __( 'Empowered by %s', 'civicrm' ), $civi_link );
508 509 510 511 512 513 514 515 516

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

519
      $empowered_enabled = TRUE;
520

521
    }
522

523
    // Start buffering
524
    ob_start();
525

526
    // Include template
527
    include( CIVICRM_PLUGIN_DIR . 'assets/templates/civicrm.shortcode.php' );
528

529
    // Save the output and flush the buffer
530
    $markup = ob_get_clean();
531

532 533 534 535 536 537 538 539 540 541
    /**
     * 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.
     */
542
    return apply_filters( 'civicrm_shortcode_render_multiple', $markup, $post_id, $shortcode );
543

544 545 546 547
  }


  /**
548 549 550
   * In order to hijack the page, we need to override the context.
   *
   * @since 4.6
551
   *
552
   * @return string The overridden context code.
553 554 555 556 557 558 559
   */
  public function get_context() {
    return 'nonpage';
  }


  /**
560
   * In order to hijack the page, we need to override the content.
561
   *
562 563 564
   * @since 4.6
   *
   * @return string The overridden content.
565 566
   */
  public function get_content( $content ) {
567

568
    global $post;
569

570
    // Is this the post?
571 572 573
    if ( ! array_key_exists( $post->ID, $this->shortcode_markup ) ) {
      return $content;
    }
574

575
    // Bail if it has multiple shortcodes
576 577 578
    if ( count( $this->shortcode_markup[$post->ID] ) > 1 ) {
      return $content;
    }
579

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

582 583 584 585
  }


  /**
586 587 588
   * In order to hijack the page, we need to override the title.
   *
   * @since 4.6
589
   *
590 591 592
   * @param string $title The existing title.
   * @param int $post_id The numeric ID of the WordPress post.
   * @return string $title The overridden title.
593 594
   */
  public function get_title( $title, $post_id ) {
595

596
    // Is this the post?
597 598 599
    if ( ! array_key_exists( $post_id, $this->shortcode_markup ) ) {
      return $title;
    }
600

601
    // Bail if it has multiple shortcodes
602 603 604
    if ( count( $this->shortcode_markup[$post_id] ) > 1 ) {
      return $title;
    }
605

606
    // Shortcodes may or may not override title
haystack's avatar
haystack committed
607 608 609
    if ( array_key_exists( $post_id, $this->post_titles ) ) {
      $title = $this->post_titles[$post_id];
    }
610

611
    return $title;
612

613 614 615 616
  }


  /**
617
   * Detect and return CiviCRM shortcodes in post content.
618
   *
619 620 621 622
   * @since 4.6
   *
   * @param str $content The content to parse.
   * @return array $shortcodes Array of shortcodes.
623 624
   */
  private function get_for_post( $content ) {
625

626
    // Init return array
627
    $shortcodes = array();
628

629
    // Attempt to discover all instances of the shortcode
630
    $pattern = get_shortcode_regex();
631 632

    if (
633 634 635 636
      preg_match_all( '/' . $pattern . '/s', $content, $matches )
      && array_key_exists( 2, $matches )
      && in_array( 'civicrm', $matches[2] ) )
    {
637

638
      // Get keys for our shortcode
639
      $keys = array_keys( $matches[2], 'civicrm' );
640

641 642 643
      foreach( $keys AS $key ) {
        $shortcodes[] = $matches[0][$key];
      }
644

645
    }
646

647
    return $shortcodes;
648

649 650 651 652
  }


  /**
653 654 655
   * Return attributes for a given CiviCRM shortcode.
   *
   * @since 4.6
656
   *
657 658
   * @param $shortcode The shortcode to parse.
   * @return array $shortcode_atts Array of shortcode attributes.
659 660
   */
  private function get_atts( $shortcode ) {
661

662
    // Strip all but attributes definitions
663 664
    $text = str_replace( '[civicrm ', '', $shortcode );
    $text = str_replace( ']', '', $text );
665

666
    // Extract attributes
667
    $shortcode_atts = shortcode_parse_atts( $text );
668

669
    return $shortcode_atts;
670

671 672 673 674
  }


  /**
675
   * Preprocess CiviCRM-defined shortcodes.
676
   *
677 678 679 680
   * @since 4.6
   *
   * @param array $atts Shortcode attributes array.
   * @return array $args Shortcode arguments array.
681 682
   */
  public function preprocess_atts( $atts ) {
683

684
    $shortcode_atts = shortcode_atts( array(
685 686 687 688 689 690 691 692 693
      'component' => 'contribution',
      'action' => NULL,
      'mode' => NULL,
      'id' => NULL,
      'cid' => NULL,
      'gid' => NULL,
      'cs' => NULL,
      'force' => NULL,
      ),
694 695 696 697 698
      $atts,
      'civicrm'
    );

    extract( $shortcode_atts );
699 700 701 702 703 704 705

    $args = array(
      'reset' => 1,
      'id'    => $id,
      'force' => $force,
    );

706
    // Construct args for known components
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731
    switch ( $component ) {

      case 'contribution':

        if ( $mode == 'preview' || $mode == 'test' ) {
          $args['action'] = 'preview';
        }
        $args['q'] = 'civicrm/contribute/transact';
        break;

      case 'event':

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

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

          default:
732
            return FALSE;
733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768
        }
        break;

      case 'user-dashboard':

        $args['q'] = 'civicrm/user';
        unset( $args['id'] );
        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';
        }
        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;

    }

769 770 771 772 773 774 775
    /**
     * Filter the CiviCRM shortcode arguments.
     *
     * This filter allows plugins or CiviExtensions to modify the attributes
     * that the 'civicrm' shortcode allows. Injected attributes and their values
     * will also become available in the $_REQUEST and $_GET arrays.
     *
776 777 778 779 780
     * @since 4.7.28
     *
     * @param array $args Existing shortcode arguments.
     * @param array $shortcode_atts Shortcode attributes.
     * @return array $args Modified shortcode arguments.
781
     */
782 783
    $args = apply_filters( 'civicrm_shortcode_preprocess_atts', $args, $shortcode_atts );

784
    // Sanity check for path
785 786 787 788 789
    if ( ! isset( $args['q'] ) ) {
      return FALSE;
    }

    return $args;
790 791 792 793 794

  }


  /**
795 796 797
   * Post-process CiviCRM-defined shortcodes.
   *
   * @since 4.6
798 799 800
   *
   * @param array $atts Shortcode attributes array
   * @param array $args Shortcode arguments array
801
   * @return array|bool $data The array data used to build the shortcode markup (or false on failure)
802 803
   */
  public function get_data( $atts, $args ) {
804

805
    // Init return array
806
    $data = array();
807

808 809 810 811
    if (!$this->civi->initialize()) {
      return FALSE;
    }

812 813 814 815 816 817
    /**
     * Filter the base CiviCRM API parameters.
     *
     * This filter allows plugins or CiviExtensions to modify the API call when
     * there are multiple shortcodes being rendered.
     *
818 819 820 821 822 823
     * @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.
824 825
     */
    $params = apply_filters( 'civicrm_shortcode_api_params', array(
826 827 828 829
      'version' => 3,
      'page' => 'CiviCRM',
      'q' => 'civicrm/ajax/rest',
      'sequential' => '1',
830
    ), $atts, $args );
831

832
    // Get the CiviCRM entity via the API
833 834 835 836
    switch ( $atts['component'] ) {

      case 'contribution':

837
        // Add event ID
838
        $params['id'] = $args['id'];
839

840
        // Call API
841
        $civi_entity = civicrm_api( 'contribution_page', 'getsingle', $params );
842

843
        // Set title
844
        $data['title'] = $civi_entity['title'];
845

846
        // Set text, if present
847 848 849 850
        $data['text'] = '';
        if ( isset( $civi_entity['intro_text'] ) ) {
          $data['text'] = $civi_entity['intro_text'];
        }
851

852 853 854 855
        break;

      case 'event':

856
        // Add event ID
857
        $params['id'] = $args['id'];
858

859
        // Call API
860
        $civi_entity = civicrm_api( 'event', 'getsingle', $params );
861

862
        // Set title
863 864
        switch ( $atts['action'] ) {
          case 'register':
865
            $data['title'] = sprintf(
866 867 868 869 870 871 872 873 874 875
              __( 'Register for %s', 'civicrm' ),
              $civi_entity['title']
            );
            break;

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

877
        // Set text, if present
878 879 880 881 882
        $data['text'] = '';
        if ( isset( $civi_entity['summary'] ) ) {
          $data['text'] = $civi_entity['summary'];
        }
        if (
883
          // Summary is not present or is empty
884
          ( !isset($civi_entity['summary']) OR empty($civi_entity['summary']) )
885
          AND
886
          // We do have a description
887
          isset( $civi_entity['description'] ) AND !empty( $civi_entity['description'] )
888
        ) {
889
          // Override with description
890 891
          $data['text'] = $civi_entity['description'];
        }
892

893 894 895 896
        break;

      case 'user-dashboard':

897
        // Set title
898 899 900 901
        $data['title'] = __( 'Dashboard', 'civicrm' );
        break;

      case 'profile':
902

903
        // Add event ID
904
        $params['id'] = $args['gid'];
905

906
        // Call API
907
        $civi_entity = civicrm_api( 'uf_group', 'getsingle', $params );
908

909
        // Set title
910
        $data['title'] = $civi_entity['title'];
911

912
        // Set text to empty
913 914 915 916 917 918
        $data['text'] = '';
        break;


      case 'petition':

919
        // Add petition ID
920
        $params['id'] = $atts['id'];
921

922
        // Call API
923
        $civi_entity = civicrm_api( 'survey', 'getsingle', $params );
924

925
        // Set title
926
        $data['title'] = $civi_entity['title'];
927

928
        // Set text, if present
929 930 931 932
        $data['text'] = '';
        if ( isset( $civi_entity['instructions'] ) ) {
          $data['text'] = $civi_entity['instructions'];
        }
933

934 935 936
        break;

      default:
937

938
        // Do we need to protect against malformed shortcodes?
939 940 941 942
        break;

    }

943 944 945 946 947 948
    /**
     * Filter the CiviCRM shortcode data array.
     *
     * This filter allows plugins or CiviExtensions to modify the data used to
     * display the shortcode when there are multiple shortcodes being rendered.
     *
949 950
     * @since 4.7.28
     *
951 952 953 954 955 956
     * @param array $data Existing shortcode data
     * @param array $atts Shortcode attributes array
     * @param array $args Shortcode arguments array
     * @return array $data Modified shortcode data
     */
    return apply_filters( 'civicrm_shortcode_get_data', $data, $atts, $args );
957 958 959 960

  }


961
} // Class CiviCRM_For_WordPress_Shortcodes ends
962 963