Skip to content
Snippets Groups Projects
civicrm.shortcodes.php 24.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • Kevin Cristiano's avatar
    Kevin Cristiano committed
    <?php
    /*
     +--------------------------------------------------------------------+
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     | CiviCRM version 5                                                  |
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     +--------------------------------------------------------------------+
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     | Copyright CiviCRM LLC (c) 2004-2019                                |
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     +--------------------------------------------------------------------+
     | 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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
     * @copyright CiviCRM LLC (c) 2004-2019
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    // This file must not accessed directly
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    if ( ! defined( 'ABSPATH' ) ) exit;
    
    
    /**
    
    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
       * Plugin object reference.
       *
       * @since 4.6
       * @access public
       * @var object $civi The plugin object reference.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
      public $civi;
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      /**
       * Stored shortcodes.
       *
       * @since 4.6
       * @access public
       * @var array $shortcodes The stored shortcodes.
       */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      public $shortcodes = array();
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      /**
       * Rendered shortcode markup.
       *
       * @since 4.6
       * @access public
       * @var array $shortcode_markup The array of rendered shortcode markup.
       */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      public $shortcode_markup = array();
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      /**
       * 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.
       */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
      public $shortcode_in_post = array();
    
    
      /**
    
    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
       */
      function __construct() {
    
    
    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', array( $this, 'render_single' ) );
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Add CiviCRM core resources when a shortcode is detected in the post content
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        add_action( 'wp', array( $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.
       *
       * Callback method for 'wp' hook, always called from WP front-end.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       *
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * @since 4.6
       *
       * @param object $wp The WP object, present but not used.
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       */
      public function prerender( $wp ) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
         * At this point, all conditional tags are available
         * @see http://codex.wordpress.org/Conditional_Tags
         */
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Bail if this is a 404
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if ( is_404() ) return;
    
    
    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
         * https://github.com/civicrm/civicrm-wordpress/pull/36
         */
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if ( have_posts() ) {
          while ( have_posts() ) : the_post();
    
            global $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
              // 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
              // Sanity check
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              if ( !empty( $shortcodes_array ) ) {
    
    
    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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                $shortcodes_present += count( $this->shortcodes[$post->ID] );
    
              }
    
            }
    
          endwhile;
        }
    
    
    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
          // 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
            // Add CSS resources for front end
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            add_action( 'wp_enqueue_scripts', array( $this->civi, 'front_end_css_load' ), 100 );
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            // Let's add dummy markup
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            foreach( $this->shortcodes AS $post_id => $shortcode_array ) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // Set flag if there are multple shortcodes in this post
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              $multiple = ( count( $shortcode_array ) > 1 ) ? 1 : 0;
    
              foreach( $shortcode_array AS $shortcode ) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                // Mimic invoke in multiple shortcode context
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                $this->shortcode_markup[$post_id][] = $this->render_multiple( $post_id, $shortcode, $multiple );
    
              }
    
            }
    
          } else {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            // Add core resources for front end
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            add_action( 'wp', array( $this->civi, 'front_end_page_load' ), 100 );
    
    
    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();
    
                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 ) ) {
                  continue;
                }
    
    
    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
                // Test for hijacking
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                if ( isset( $atts['hijack'] ) AND $atts['hijack'] == '1' ) {
                  add_filter( 'civicrm_context', array( $this, 'get_context' ) );
                }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                // Store corresponding markup
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                $this->shortcode_markup[$post->ID][] = do_shortcode( $shortcode );
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                // Test for hijacking
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                if ( isset( $atts['hijack'] ) AND $atts['hijack'] == '1' ) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                  // Ditch the filter
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                  remove_filter( 'civicrm_context', array( $this, 'get_context' ) );
    
    
    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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                  add_filter( 'single_post_title', array( $this->civi, 'single_page_title' ), 50, 2 );
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                  // Overwrite content
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                  add_filter( 'the_content', array( $this, 'get_content' ) );
    
                }
    
              endwhile;
            }
    
    
    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
       */
      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;
        if ( is_object($post) ) {
          if ( !empty( $this->shortcode_markup ) ) {
            if ( isset( $this->shortcode_markup[$post->ID] ) ) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // Set counter flag
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              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
              // 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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $args = $this->preprocess_atts( $atts );
    
    
    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
        // invoke() requires environment variables to be set
        foreach ( $args as $key => $value ) {
          if ( $value !== NULL ) {
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            set_query_var($key, $value);
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $_REQUEST[$key] = $_GET[$key] = $value;
          }
        }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Kick out if not CiviCRM
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if (!$this->civi->initialize()) {
          return '';
        }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Check permission
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $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';
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        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
    
    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
       */
      private function render_multiple( $post_id = FALSE, $shortcode = FALSE, $multiple = 0 ) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Get attributes
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $atts = $this->get_atts( $shortcode );
    
    
    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
        // Sanity check for improperly constructed shortcode
        if ( $args === FALSE ) {
          return '<p>' . __( 'Do not know how to handle this shortcode.', 'civicrm' ) . '</p>';
        }
    
        // 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
        // Sanity check
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if ( $data === FALSE ) return '';
    
    
    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
        // Init title flag
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $show_title = TRUE;
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Default link
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $link = get_permalink( $post_id );
    
    
    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 CIvi 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 ) {
    
          $links = array();
          foreach( $args AS $var => $arg ) {
            if ( ! empty( $arg ) AND $var != 'q' ) {
              $links[] = $var . '=' . $arg;
            }
          }
          $query = implode( '&', $links );
    
          // $absolute, $frontend, $forceBackend
          $base_url = $this->civi->get_base_url(TRUE, FALSE, FALSE);
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // Init query parts
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $queryParts = array();
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
          // 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);
    
    
    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
            if (isset($args['q'])) {
              $base_url = trailingslashit( $base_url ) . str_replace('civicrm/', '', $args['q']) . '/';
            }
            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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if ( !$multiple ) {
    
          if ( isset( $atts['hijack'] ) AND $atts['hijack'] == '1' ) {
    
    
    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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            add_filter( 'the_title', array( $this, 'get_title' ), 100, 2 );
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            // Overwrite content
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            add_filter( 'the_content', array( $this, 'get_content' ) );
    
    
    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;
        if ( isset( $data['text'] ) AND ! empty( $data['text'] ) ) {
          $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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if ( $config->empoweredBy == 1 ) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          // Footer enabled - define it
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          $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 );
    
    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 );
    
          $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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        include( CIVICRM_PLUGIN_DIR . 'assets/templates/civicrm.shortcode.php' );
    
    
    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
       */
      public function get_content( $content ) {
    
        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 ) ) {
          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 ) {
          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
       */
      public function get_title( $title, $post_id ) {
    
    
    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 ) ) {
          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 ) {
          return $title;
        }
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Shortcodes may or may not override title
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        if ( array_key_exists( $post_id, $this->post_titles ) ) {
          $title = $this->post_titles[$post_id];
        }
    
        return $title;
    
      }
    
    
      /**
    
    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
       */
      private function get_for_post( $content ) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Init return array
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $shortcodes = array();
    
    
    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 (
          preg_match_all( '/' . $pattern . '/s', $content, $matches )
          && array_key_exists( 2, $matches )
          && in_array( 'civicrm', $matches[2] ) )
        {
    
    
    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' );
    
          foreach( $keys AS $key ) {
            $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
       */
      private function get_atts( $shortcode ) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Strip all but attributes definitions
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $text = str_replace( '[civicrm ', '', $shortcode );
        $text = str_replace( ']', '', $text );
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Extract attributes
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $shortcode_atts = shortcode_parse_atts( $text );
    
        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
       */
      public function preprocess_atts( $atts ) {
    
    
        $shortcode_atts = shortcode_atts( array(
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          'component' => 'contribution',
          'action' => NULL,
          'mode' => NULL,
          'id' => NULL,
          'cid' => NULL,
          'gid' => NULL,
          'cs' => NULL,
          'force' => NULL,
          ),
    
          $atts,
          'civicrm'
        );
    
        extract( $shortcode_atts );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
        $args = array(
          'reset' => 1,
          'id'    => $id,
          'force' => $force,
        );
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Construct args for known components
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        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:
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
                return FALSE;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            }
            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;
    
        }
    
    
        /**
         * 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.
         *
    
    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 );
    
        // Sanity check for path
        if ( ! isset( $args['q'] ) ) {
          return FALSE;
        }
    
        return $args;
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
       * Post-process CiviCRM-defined shortcodes.
       *
       * @since 4.6
    
    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
       */
      public function get_data( $atts, $args ) {
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Init return array
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        $data = array();
    
        if (!$this->civi->initialize()) {
          return FALSE;
        }
    
    
        /**
         * Filter the base CiviCRM API parameters.
         *
         * This filter allows plugins or CiviExtensions 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.
    
         */
        $params = apply_filters( 'civicrm_shortcode_api_params', array(
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
          'version' => 3,
          'page' => 'CiviCRM',
          'q' => 'civicrm/ajax/rest',
          'sequential' => '1',
    
        ), $atts, $args );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        // Get the CiviCRM entity via the API
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
        switch ( $atts['component'] ) {
    
          case 'contribution':
    
    
    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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $civi_entity = civicrm_api( 'contribution_page', 'getsingle', $params );
    
    
    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'] = '';
            if ( isset( $civi_entity['intro_text'] ) ) {
              $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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $civi_entity = civicrm_api( 'event', 'getsingle', $params );
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            // Set title
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            switch ( $atts['action'] ) {
              case 'register':
                $data['title'] = sprintf(
                  __( 'Register for %s', 'civicrm' ),
                  $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'] = '';
            if ( isset( $civi_entity['summary'] ) ) {
              $data['text'] = $civi_entity['summary'];
            }
            if (
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // Summary is not present or is empty
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              ( !isset($civi_entity['summary']) OR empty($civi_entity['summary']) )
              AND
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              // We do have a description
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
              isset( $civi_entity['description'] ) AND !empty( $civi_entity['description'] )
            ) {
    
    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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $data['title'] = __( 'Dashboard', 'civicrm' );
            break;
    
          case 'profile':
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            // Add event ID
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $params['id'] = $args['gid'];
    
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            // Call API
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $civi_entity = civicrm_api( 'uf_group', 'getsingle', $params );
    
    
    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
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
            $civi_entity = civicrm_api( 'survey', 'getsingle', $params );
    
    
    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'] = '';
            if ( isset( $civi_entity['instructions'] ) ) {
              $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.
         *
         * This filter allows plugins or CiviExtensions 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
         *
    
         * @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 );
    
    Kevin Cristiano's avatar
    Kevin Cristiano committed
    } // Class CiviCRM_For_WordPress_Shortcodes ends