Skip Navigation

[Resolved] Load different layouts via php conditionally

The Toolset Community Forum is closed, for technical support questions, please head on to our Toolset Professional Support (for paid clients), with any pre-sale or admin question please contact us here.
This support ticket is created 6 years, 11 months ago. There's a good chance that you are reading advice that it now obsolete.
This is the community support forum for Types plugin, which is part of Toolset. Toolset is a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients and people who registered for Types community support can post in it.

Sun Mon Tue Wed Thu Fri Sat
8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 - -
13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 - -

Supporter timezone: America/New_York (GMT-04:00)

This topic contains 12 replies, has 3 voices.

Last updated by Franck 6 years, 11 months ago.

Assisted by: Christian Cox.

Author
Posts
#596725

Hi, i'm trying to integrate AMP in my site. Creating a plugin for toolset.

I need to show a differente template once the amp parameter in the url is like "?amp=1".
This is simple for me: I can use $_GET parameter to retrive if it is true, but i need your help to know how to change layout onche my php condition is true.

My solution could be to create 2 layouts templates:
1. The Default one
2. The one called once the amp parameter is true

How can i integrate it ?

#596981

Hi, you can use the filter "get_layout_id_for_render" to specify a different Layout ID for any post:

function apply_layout_by_post_id( $id, $layout ){
  global $post;
  $preferred_layout = 123;

  if( $post->ID === 456 ){
      return $preferred_layout;
  }
  return $id;
}

add_filter('get_layout_id_for_render', 'apply_layout_by_post_id', 10, 2);

Change 123 to the desired Layout ID, change 456 to the Post ID.

#597050

Ok Christian it works.

While building AMP pages google wants the code include custom pure HTML and also no other .js included:
hidden link

Like the AMP example belove:

<!doctype html>
<html amp lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello, AMPs</title>
    <link rel="canonical" href="<em><u>hidden link</u></em>">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <script type="application/ld+json">
      {
        "@context": "<em><u>hidden link</u></em>",
        "@type": "NewsArticle",
        "headline": "Open-source framework for publishing content",
        "datePublished": "2015-10-07T12:02:41Z",
        "image": [
          "logo.jpg"
        ]
      }
    </script>
    <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
    <script async src="<em><u>hidden link</u></em>"></script>
  </head>
  <body>
    <h1>Welcome to the mobile web</h1>
  </body>
</html>

But while loading also a new empty layout types output all my website html. I'd need to use newone HTML code.
The way could be to use custom template or there is another way using layouts to exclude auto-generated html?

#597457

But while loading also a new empty layout types output all my website html.
Yes, this is standard WordPress behavior. The WordPress engine generates an entire page, complete with stylesheets and scripts, at each URL. I'm not really familiar with AMP and how it works, but I'm afraid Layouts can't help you modify the markup in the header and footer of your HTML, or manipulate which JavaScript files and stylesheets are included in the head. This will require some custom code in your theme that enqueues and dequeues the appropriate scripts and stylesheets. Most themes and plugins enqueue their own scripts automatically, so by default they would not be compatible.

#597460

Ok, as i've seen in a plugin you raccomanded to me in another ticket: "Views Output Format" it outputs a json code using wp-views functions this is the plugin code:

<?php
/*
Plugin Name: Views Output Formats - JSON / XML Export
Plugin URI: http://wordpress.org/extend/plugins/views-output-formats
Description: Provides JSON and XML output formats for Toolset Views
Version: 2.1
Author: khromov
Author URI: <em><u>hidden link</u></em>
License: GPL2
*/

class Views_Output_Formats
{
	const text_domain = "vof";

	function __construct()
	{
		/**
		 * Translation support
		 **/
		load_plugin_textdomain(self::text_domain, false, basename( dirname( __FILE__ ) ) . '/languages' );

		/**
		 * Register hooks, languages etc
		 **/
		register_activation_hook(__FILE__ , array( 'Views_Output_Formats', 'activate' ));
		register_deactivation_hook(__FILE__ , array( 'Views_Output_Formats', 'deactivate' ));

		/**
		 * Register menu item
		 */
		add_action('admin_menu', array( &$this, 'register_admin_menus'));

		/**
		 * Add URL endpoints for accessing different formats
		 */
		add_filter('query_vars', array(&$this, 'register_vars'));
		add_action('wp', array(&$this, 'register_endpoints')); //pre_get_posts is faster, but we can't use some functions there...
	}

	function register_vars($vars)
	{
		$vars[] = 'vof_id';
		$vars[] = 'vof_format';
		$vars[] = 'vof_token';
		return $vars;
	}

	function register_endpoints($query)
	{
		//Sanity checks
		if(	get_query_var('vof_id') !== '' 		&&
			get_query_var('vof_token') !== '' 	&&
			get_option('vof_token') !== false 	&&
			(get_query_var('vof_token') === get_option('vof_token') || get_query_var('vof_token') === $this->get_view_vof_token((int)get_query_var('vof_id'))) &&
			get_post_type((int)get_query_var('vof_id')) === 'view' &&
			function_exists('wpv_filter_get_posts')
		)
		{
			//Pick format
			$format = (get_query_var('vof_format') === 'xml') ? 'xml' : 'json';

			/* @var WP_Views $WP_Views */
			global $WP_Views;

			//Get the View query type
			$view_settings = $WP_Views->get_view_settings((int)get_query_var('vof_id'));

			//Prepare string for output
			$output = '';

			//Prepare string for data
			$result = array();

			//Set headers
			if($format === 'json')
				header('Content-type: application/json');
			else
				header('Content-Type: text/xml');

			//Taxonomy query
			if($view_settings['query_type'][0] === 'taxonomy')
			{
				$result['taxonomies'] = $WP_Views->taxonomy_query($view_settings);

				if($format === 'json')
					$output =  json_encode($result);
				else
					$output = Views_Output_Formats_XMLSerializer::generateValidXmlFromArray($result, '', 'taxonomy');
			}
			else if($view_settings['query_type'][0] === 'users') //User query
			{
				$result['users'] = $WP_Views->users_query($view_settings);

				//Filter sensitive information
				foreach($result['users'] as &$user)
				{
					$user->user_pass = '';
					$user->user_activation_key = '';
				}

				if($format === 'json')
					$output =  json_encode($result);
				else
					$output = Views_Output_Formats_XMLSerializer::generateValidXmlFromArray($result, '', 'users');
			}
			else //Posts query
			{
				//Query results. This is done differently from Taxonomy and Users queries
				$query_result = wpv_filter_get_posts((int)get_query_var('vof_id'));

				//Add in custom fields
				$posts_fixed['post'] = $this->views_output_merge_custom_fields($query_result->posts);

				//TODO: Add in taxonomies
				//$posts_fixed['post'] = views_output_merge_taxonomies($query_result->posts);

				//Finalize array
				$posts_finished = array('posts' => $posts_fixed);

				if($format === 'json')
				{
					$posts_json = array('posts' => $this->views_output_merge_custom_fields($query_result->posts));
					$output = json_encode($posts_json);
				}
				else
				{
					//Do some additional transformation to get the output format we want
					$posts_tmp = array();

					//Special condition for no results
					if(sizeof($query_result->posts)!==0)
					{
						$i = 0;
						foreach($posts_finished as $post)
						{
							foreach($post['post'] as $post_inner)
							{
								$posts_tmp['posts'][$i] = $post_inner;
								$i++;
							}
						}
					}
					else
						$posts_tmp['posts'] = array();

					echo Views_Output_Formats_XMLSerializer::generateValidXmlFromArray($posts_tmp, '', 'post');
				}
			}

			//Print output
			echo $output;

			//Early termination
			die();
		}
	}

	function register_admin_menus()
	{
		add_submenu_page( 'options-general.php', __( "Views Output Formats", self::text_domain), __( "Views Output Formats", self::text_domain ), 'manage_options', 'vof', array( &$this, 'admin_main' ));
	}

	function admin_main()
	{
		$views = $this->get_all_views();
		$views_html_output = '<table>';
		/* WP_Query $views */
		foreach($views->get_posts() as $view)
		{
			/* @var WP_Post $view */
			$views_html_output .= '
									<tr>
										<td>
											'. $view->post_title .'
										</td>
										<td>
											<a href="'. get_bloginfo('url') .'/?vof_id='.$view->ID.'&vof_format=xml&vof_token='. $this->get_view_vof_token($view->ID) .'">XML</a>
											|
											<a href="'. get_bloginfo('url') .'/?vof_id='.$view->ID.'&vof_format=json&vof_token='. $this->get_view_vof_token($view->ID) .'">JSON</a>
										</td>
									</tr>
									';
		}

		$views_html_output .= '</table>';
		ob_start();
		?>
		<div class="wrap">
			<?php screen_icon(); ?>
			<h2>
				<?php _e( 'Views Output Formats', 'dfwmdt' ); ?>
			</h2>

			<div class="info" style="padding-top: 10px;">
				<?php _e( 'From this screen you can get the URL links for all your Views in XML or JSON formats.', self::text_domain ); ?>
				<p>
					<?php _e('Your global secret', self::text_domain); ?> <abbr title="<?php _e('The token can be reset by deactivating and reactivating the plugin.', self::text_domain); ?>"><?php _e('API token',self::text_domain); ?> </abbr> <?php _e('is:', self::text_domain); ?> <strong><?php echo get_option('vof_token'); ?></strong> <br/>
					<?php _e('Each View also has an individual API token that is valid for that view alone.', self::text_domain); ?> <br/>
				</p>
				<p>
					<?php echo $views_html_output; ?>
				</p>
			</div>
		</div>
		<?php
		echo ob_get_clean();
	}

	/**
	 * Returns a list of all views
	 */
	function get_all_views()
	{
		$args = array('post_type' => 'view', 'order' => 'ASC', 'posts_per_page' => -1, 'post_status' => 'publish');
		return new WP_Query($args);
	}

	/** Adds custom fields to the post and returns it */
	function views_output_merge_custom_fields($posts)
	{
		$posts = array_map(array(&$this, 'views_add_custom_fields_for_post_map'), $posts);
		return $posts;
	}

	function views_add_custom_fields_for_post_map($post, $exclude_hidden_fields = 1)
	{
		//Aggregate custom fields for the post
		$custom_fields = get_post_custom($post->ID);

		$post->custom_fields = array();

		//Main Custom Field loop
		foreach($custom_fields as $key => $value)
		{
			if(sizeof($custom_fields[$key]) === 1)
				$post->custom_fields[$key] = $value[0];
			else
			{
				for($i = 0; $i < sizeof($value); $i++)
					$post->custom_fields[$key]['value_'.($i+1)] = $value[$i];
			}

			//Add in thumbnail url if it exists
			if($key === '_thumbnail_id' && isset($value[0]) && intval($value[0]) !== 0)
			{
				$featured_image_tmp = wp_get_attachment_image_src(intval($value[0]), 'full');
				$post->custom_fields['_thumbnail_url'] = $featured_image_tmp[0];
			}
		}
		return $post;
	}

	/**
	 * Return unique token for a View
	 *
	 * The token is derived from the master token, which should
	 * never be used publicly.
	 */
	function get_view_vof_token($view_id)
	{
		//Use the secondary token to generate an unique token for a specific view
		return md5((string)$view_id . get_option('vof_secondary_token') . get_option('vof_token'));
	}

	/**
	 * Plugin activation function
	 **/
	static function activate()
	{
		//Create a random API token
		$token = md5(wp_generate_password());
		$secondary_token = md5(wp_generate_password());
		add_option('vof_token', $token);
		add_option('vof_secondary_token', $secondary_token);
	}

	/**
	 * Plugin deactivation function
	 */
	static function deactivate()
	{
		//If we re-initialize the plugin, the API keys will be changed
		delete_option('vof_token');
		delete_option('vof_secondary_token');
	}
}

class Views_Output_Formats_XMLSerializer
{
	//functions adopted from <em><u>hidden link</u></em>
	public static function generateValidXmlFromObj(stdClass $obj, $node_block='nodes', $node_name='node')
	{
		return self::generateValidXmlFromArray(get_object_vars($obj), $node_block, $node_name);
	}

	public static function generateValidXmlFromArray($array, $node_block='nodes', $node_name='node')
	{
		$xml = '<?xml version="1.0" encoding="UTF-8" ?>';

		//$xml .= '<' . $node_block . '>';
		$xml .= self::generateXmlFromArray($array, $node_name);
		//$xml .= '</' . $node_block . '>';

		return $xml;
	}

	private static function generateXmlFromArray($array, $node_name)
	{
		$xml = '';

		if (is_array($array) || is_object($array))
		{
			foreach ($array as $key => $value)
			{
				//Check for invalid XML element names
				$key = (sanitize_key($key) === '') ? 'field' : sanitize_key($key);

				if (is_numeric($key))
				{
					$key = $node_name;
				}

				//Special case for outer wrapper
				//if($node_name === false)
				//	$xml .= self::generateXmlFromArray($value, $node_name);
				//else
				$xml .= '<' . $key . '>' . self::generateXmlFromArray($value, $node_name) . '</' . $key . '>';
			}
		}
		else
		{
			$xml = htmlspecialchars($array, ENT_QUOTES);
		}

		return $xml;
	}
}

//Init plugin
$vof = new Views_Output_Formats();

I would like to do the same generating my custom html retriving it from a wp-types custom template not including any type of code.

My question could be now:
Is there any toolset function to use in php to echo just the (views || custom-template || layout) output without any other elements like the code is sent you ?

#597467

Christina do you think ob_start() function will help me ?

#597753

Hi, please refer to the Views API documentation here:
https://toolset.com/documentation/programmer-reference/views-api/
render_view is the PHP function that you can use to render the output of a View programmatically. However, I do not think this will help you remove extra JavaScript from the header of a page generated by WordPress because you must include this render_view function somewhere on your site, and any page in your site is going to have the header generated by WordPress.

#597759

Hi, i make it work with this code:

add_action( 'wp', 'romapiu_check_amp' );

function romapiu_check_amp () {
  if ( isset( $_GET['amp'] ) && is_singular() ) {
    ob_start("romapiu_custom_output");
  }
}

//OUTPUT DEL CONTENT TEMPLATE
function romapiu_custom_output() {
  $content_template_id = 4819;
  $post_type = get_post_type( get_the_ID() );
  return render_view_template( $content_template_id, get_the_ID() );

}

In the content template i put the AMP HTML CODE and it works! I can use also [types... ] definitions.
The only issue is that i can't use [wpv-view name="..."] code in the content template. I don't know why. I think i have to try with a custom shortcode.

I'm trying in these hours, if you can help me i'll appreciate

#597781

Hi Cristian,
with ob_start() function i can output custom php with no other things but while:

return render_view_template( $content_template_id, get_the_ID() );

WORKS

return  render_view(array('name' =>'amp-side-bar'));

DOES NOT WORK

Can you help me ?

#597788

These are the debug console.log notices and errors:

[11-Dec-2017 17:13:40 UTC] PHP Notice:  Use of undefined constant TOOLSET_REST_FOLDER - assumed 'TOOLSET_REST_FOLDER' in /var/www/vhosts/romapiu.it/httpdocs/wp-content/plugins/toolset-rest-master/toolset-rest.php on line 41
[11-Dec-2017 17:13:40 UTC] PHP Notice:  Undefined index: 00 in /var/www/vhosts/romapiu.it/httpdocs/wp-includes/class-wp-locale.php on line 312
[11-Dec-2017 17:13:40 UTC] PHP Notice:  Trying to get property of non-object in /var/www/vhosts/romapiu.it/httpdocs/wp-content/plugins/wp-views/embedded/inc/wpv-api.php on line 262
[11-Dec-2017 17:13:40 UTC] PHP Fatal error:  print_r(): Cannot use output buffering in output buffering display handlers in /var/www/vhosts/romapiu.it/httpdocs/wp-content/plugins/wp-views/embedded/inc/wpv-filter-query.php on line 756
[11-Dec-2017 17:13:42 UTC] PHP Notice:  Use of undefined constant TOOLSET_REST_FOLDER - assumed 'TOOLSET_REST_FOLDER' in /var/www/vhosts/romapiu.it/httpdocs/wp-content/plugins/toolset-rest-master/toolset-rest.php on line 41
 
#597813

You can try to start and stop the output buffer like this:

ob_start();
$output = render_view( array('name' =>'posts') );
ob_end_clean();
echo $output;
exit;
#597899

Thank you Christian!!
You are a Genius!

It Works!

Not thank to you i can implement AMP in my projects. It is a very good news becuase Amp is the new standard for google for mobile pages.

Thank you!!!

#628605

Hello,

Can i have somebody could you help me to understand what i have to do if i want tu use AMP with toolset ?

What i have to put in fonction php ?

Thanks a lot.

The forum ‘Types Community Support’ is closed to new topics and replies.