• After hours seeking through the WordPress sources it I was unable to find ANY resonable method of creating a front end page from a plugin. My goal was simple, I wanted http://mysite.com/friends to show a page generated by my plugin. This is a multi-site installation and I do not want blog owners to be able to eliminate this page. My final implementation doesn’t involve users blogs but it could.

    wp-includes/theme.php: I added this function

    function get_extension_page_template() {
        $page = get_queried_object();
        $templates = array($page->ID.'.php');
        return get_query_template($page->ID,$templates);
    }

    wp-includes/template-loader.php: I added this just ofter the if(is_404() line(near line 8)
    elseif ( is_extension_page() && $template = get_extension_page_template()) :

    wp-includes/query.php: I added two functions

    function set_extension_page($page,$object) {
        global $wp_query;
        return $wp_query->set_extension_page($page,$object);
    }
    
    function is_extension_page() {
      global $wp_query;
    	return $wp_query->is_extension_page();
    }

    wp-includes/query.php: I added two properties to the WP_Query class

    var $extension_page = null;
      var $extension_page_object = null;

    wp-includes/query.php: I added two methods to the WP_Query class

    function set_extension_page($page,$object) {
          $this->extension_page_object = $object;
          $this->extension_page = $page;
      }
      function is_extension_page() {
         return isset($this->extension_page);
      }

    wp-includes/query.php: I changed the get_queried_object method in the WP_Query class

    function get_queried_object() {
    		if ( isset($this->queried_object) )
    			return $this->queried_object;
    
        if (isset($this->extension_page_object)) {
            return $this->extension_page_object;
        }
    		$this->queried_object = NULL;
    		$this->queried_object_id = 0;
    
    		if ( $this->is_category || $this->is_tag || $this->is_tax ) {
    			$tax_query_in_and = wp_list_filter( $this->tax_query->queries, array( 'operator' => 'NOT IN' ), 'NOT' );
    
    			$query = reset( $tax_query_in_and );
    
    			if ( 'term_id' == $query['field'] )
    				$term = get_term( reset( $query['terms'] ), $query['taxonomy'] );
    			else
    				$term = get_term_by( $query['field'], reset( $query['terms'] ), $query['taxonomy'] );
    
    			if ( $term && ! is_wp_error($term) )  {
    				$this->queried_object = $term;
    				$this->queried_object_id = (int) $term->term_id;
    
    				if ( $this->is_category )
    					_make_cat_compat( $this->queried_object );
    			}
    		} elseif ( $this->is_post_type_archive ) {
    			$this->queried_object = get_post_type_object( $this->get('post_type') );
    		} elseif ( $this->is_posts_page ) {
    			$page_for_posts = get_option('page_for_posts');
    			$this->queried_object = & get_page( $page_for_posts );
    			$this->queried_object_id = (int) $this->queried_object->ID;
    		} elseif ( $this->is_singular && !is_null($this->post) ) {
    			$this->queried_object = $this->post;
    			$this->queried_object_id = (int) $this->post->ID;
    		} elseif ( $this->is_author ) {
    			$this->queried_object_id = (int) $this->get('author');
    			$this->queried_object = get_userdata( $this->queried_object_id );
    		}
    
    		return $this->queried_object;
    	}

    wp-includes/class-wp.php: I changed the handle_404 method to the following

    function handle_404() {
    		global $wp_query;
    
    		if ( !is_admin() && ( 0 == count( $wp_query->posts ) ) && !is_404() && !is_robots() && !is_search() && !is_home() ) {
    			// Don't 404 for these queries if they matched an object.
    			if ( ( is_extension_page() || is_tag() || is_category() || is_tax() || is_author() || is_post_type_archive() ) && $wp_query->get_queried_object() && !is_paged() ) {
    				if ( !is_404() )
    					status_header( 200 );
    				return;
    			}
    
    			$wp_query->set_404();
    			status_header( 404 );
    			nocache_headers();
    		} elseif ( !is_404() ) {
    			status_header( 200 );
    		}
    	}

    The final result is that I can create an object in plugins on patched sites and test for certain conditions, such as $blogpage = $this->ID and then call set_extension_page($this->ID,$this); to register the page to be displayed. The theme must also have a template setup for that plugin which is named (first parameter of set_extension_page).php but its better than nothing.

    I admit this is just an ugly hack, but it works. It would be nice to see a feature like this added to wordpress in the future.

Viewing 4 replies - 1 through 4 (of 4 total)
  • Why not use ‘template_redirect’ hook, check for the URL, echo the content and then kill the script?

    Thread Starter rritoch

    (@rritoch)

    shazdeh,

    I really don’t like the idea of prematurely killing a script as that will prevent other plugins from being able to complete their tasks. The implementation of the template selection though should probably be done with a filter instead of the current method. The registering of a object is still critical though. When I get a chance I will likely do some additional work on this hack to reduce the complexity and increase the usefulness of it.

    The template_redirect hook happens just before including the correct template file, or building the proper feed. Nothing happens after that. So it’s perfect for the job.
    Or, check for the url on pre_get_posts, if it’s /friends then change the global $post->post_content value and that’s it.

    Hi Rritoch,

    I’d suggest posting this over on wordpress.stackexchange.com, i’d love to see the guys over there tackle this hack, it’s an interesting question.

    I think you’d get more feedback posting it over there and is why i’m suggesting it.. 😉

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘Creating a plugin page hack’ is closed to new replies.