Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature request] Closures as a value for the template setting #22

Closed
wujekbogdan opened this issue Dec 6, 2017 · 4 comments
Closed

Comments

@wujekbogdan
Copy link

At the moment a template can take only a string as an argument. It would be great if we also could use a closures. The closure could take $matches and ideally s $wp_query (if it's available at this point) as an argument.

Example:

$routes->addRoute( new QueryRoute(
	'my/route/{param}',
	function ( array $matches ) {
		return [
			'post_type' => 'my_post_type',
		];
	},
	[
		'template' => function ( array $matches, \WP_Query $query ) {
			if ( $matches['param'] === 'something' && $query->post_count > 1 ) {
				return 'a-tempalte.php';
			}

			return 'another-template.php';
		}
	]
) );
@gmazzap
Copy link
Collaborator

gmazzap commented Dec 18, 2017

Hi @wujekbogdan yep, nothing against that. Don't have much time these days, but if you have time to work on a PR I could review & accept... Or you can wait a bit :)

gmazzap added a commit that referenced this issue Dec 24, 2017
@gmazzap
Copy link
Collaborator

gmazzap commented Dec 24, 2017

@wujekbogdan I liked the idea and worked a bit on it.

However, it was no possible to implement it as you described.

Because of compatibilty reasons, the callback must be executed before the "before" callback of the route.

It means that WP_Query is not parsed yet so won't be possible to do pass a WP_Query object to the callback.

In next version I plan to improve this, but for now it works like this:

$routes->addRoute( new QueryRoute(
	'my/route/{param}',
	function ( array $matches ) {
		return [
			'post_type' => 'my_post_type',
		];
	},
	[
		'template' => function ( array $vars, \WP $wp, array $matches ) {
			if ( $matches['param'] === 'something') {
				return 'a-template.php';
			}

			return 'another-template.php';
		}
	]
) );

So you get the query variables that are going to be set, the WP instance and the matches, but not the query object.

But with a little trick you can obtain your wanted results. First you could define a class like this:

class ConditionalTemplate
{
  private $condition;

  public function __construct(callable $condition)
  {
    $this->condition = $condition;
  }

  public function __invoke(array $vars, \WP $wp, array $matches)
  {
    add_action('template_redirect', function () use ($matches) {

      global $wp_query; // at this point the query is available
      $cb = $this->condition;
      $template = $cb($matches, $wp_query);

      $template and add_filter('template_include', function () use ($template) {
        return $template;
      }, PHP_INT_MAX);
    }, 0);

    return null;
  }
}

and then:

$routes->addRoute( new QueryRoute(
  'my/route/{param}',
  function ( array $matches ) {
    return [
      'post_type' => 'my_post_type',
    ];
  },
  [
    'template' => new ConditionalTemplate(function (array $matches, \WP_Query $query) {
      if ($matches['param'] === 'something' && $query->post_count > 1) {
        return '/path/to/a-template.php';
      }
      return locate_template('index.php');
    });
  ]
) );

This should work quite fine, waiting for easier way on Cortex v2 :)

Note that this feature is not released, you could test by requiring Cortex from branch refactoring-fastorute I could merge after some feedback.

@wujekbogdan
Copy link
Author

wujekbogdan commented Dec 24, 2017

@gmazzap

I liked the idea and worked a bit on it.

That's great. Thank you very much!

But with a little trick you can obtain your wanted results.

Thanks for the example. It's a bit hacky, but your implementation is quite clean (and quite smart too) anyway.


This should work quite fine, waiting for easier way on Cortex v2 :)

So, you are working on a new version of Cortex? What features can we expect?
Sorry for the offtopic, but I'm very curious what features the new version will bring. For example, I would love to be able not only to define routes but also to easily create URL-s that point to a specific route... but it such change would require named routes (that can possibly break the backward compatibility). Have a look at vue-router named routes and the router.push() method - this is what I'm talking about.

@gmazzap
Copy link
Collaborator

gmazzap commented Dec 26, 2017

@wujekbogdan named routes and URL generation were a thing in Cortex 0.* (based on Symphony routing component) and on the Cortex predecessor "Clever Rules" (now abandoned). They were removed from Cortex 1.* switching to FastRoute. But, yes, you can expect they be there on v2.
Besides of that, v2 will use latest version of FastRoute with native support for route groups, some caching mechanism and drop support for PHP 5. ETA: no idea, sometime in 2018, maybe.

@gmazzap gmazzap closed this as completed Jul 22, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants