Jump to content

RockFrontend ๐Ÿš€๐Ÿš€ Take your ProcessWire Frontend Development to the Next Level


bernhard
 Share

Recommended Posts

Just starting to use this and I like what I seeย ?.

I have always used markup regions for my front-end rendering and am wondering what is the best way of making these play with RockFrontend and Latte (if at all)?

I like the renderMatrix method, but it just renders flat html when the repeaters have structure (depth), so I built an analogue - renderMatrixIndented, which renders the structure via <div> tags. Here is some code (which lives in my custom page class) in case it is of any use.

/**
	 * Render RepeaterMatrix fields with depth
	 * Each level receives a div with a class name equal to the item type
	 * @return string
	 */
	public function renderMatrixIndented($items, $vars, $options, $rockfrontend)
	{
		$out = '';
		$depth = -1;
		$divCount = 0;
		foreach ($items as $item) {
			$field = $item->getForField();
			$type = $item->type;
			$depthChange = $depth - $item->depth + 1;
			if ($depthChange > 0) {
				while($depthChange--) {
					$out.= '</div>';
					$divCount--;
				}
			}
			$out.= "<div class={$type} style='{$item->theme_style}'>";
			$divCount += 1;
			$file = "fields/$field/$type";
			$vars = array_merge($vars, ['page' => $item]);
			$out .= $rockfrontend->render($file, $vars, $options);
			$depth = $item->depth;
		}
		while($divCount--) {
			$out.= "</div>";
		}
		// if renderMatrix was called from a latte file we return HTML instead
		// of a string so that we don't need to call |noescape filter
		$trace = Debug::backtrace()[1]['file'];
		if (strpos($trace, "/site/assets/cache/Latte/") === 0) $out = new Html($out);
		bd($out, 'OUT');
		return $out;
	}

No doubt this could be generalised somewhat. BTW, it also adds some styling to each item if it has a field 'theme_style' but that could probably live elsewhere. I am using this in a simple page builder where class names can correspond to grid areas.

Link to comment
Share on other sites

15 hours ago, MarkE said:

I have always used markup regions for my front-end rendering and am wondering what is the best way of making these play with RockFrontend and Latte (if at all)?

Interesting need. I've stopped using MarkupRegions because it was more confusing than helpful for me. But you can use them with RockFrontend of course.

RockFrontend does not care where the markup comes from and so does ProcessWire. So for example you could just render a latte file from your home.php file that holds the markup for the markup region and then in your main markup file (or any rendered LATTE file) you simply add that region and it will hold the content of the markup you put in home.php

If that sounds confusing I'm sorry, but that's how it is when using markup regions ?ย 

// home.php
<?php
echo $rockfrontend->render("sections/home.latte");

// sections/home.latte
<div id='foo'>
  <h1>{$page->title} - foo!</h1>
</div>
  
// _main.php
<html>
  <body>
  <?= $rockfrontend->render('sections/main.latte') ?>
  </body>
</html>

// sections/main.latte
<div>This is main latte</div>

<div id="foo"></div>

<div>End of main latte file</div>

Does that make sense?

Link to comment
Share on other sites

7 hours ago, bernhard said:

Does that make sense?

Yes and no. I couldn't get your code to work. It seems like you need to put the matching <div> in the php file, not the latte file. So, with your example (where<div id="foo"> matches an id in _main.php)

// home.php

<div id='foo'>
<?= $rockfrontend->render("sections/home.latte"); ?>
</div>

// sections/home.latte
<h1>{$page->title} - foo!</h1>

ย 

Afterthought: However, it seems that Latte makes markup regions all rather unnecessary and confusing - easiest just to directly render latte files from _main.php. For flexibility, I haveย 

// In _main.php:
<body>
<?= $rockfrontend->render("layouts/main.latte"); ?>
</body>

// In layouts/main.latte:
{include "$page->template.latte"}
// plus whatever else you want (sections etc)

// Then whatever in the template latte file

Unfortunately, it seems you still need the php template file, even if empty. It would be nice to get rid of that...

Link to comment
Share on other sites

On 9/29/2022 at 7:48 PM, MarkE said:

I couldn't get your code to work. It seems like you need to put the matching <div> in the php file, not the latte file.

No. I just tried it again:

// home.php
<?php

namespace ProcessWire;

echo $rockfrontend->render("home.latte");

// home.latte
<div id="markupregion">home.latte</div>
  
// footer.latte
<div id="markupregion">
  original content
</div>
<section>I am the footer</section>

Neither PW nor RockFrontend care about where the markup comes from. You just need to make sure that your region content is above the region markup. This is what it looks like when disabling $config->useMarkupRegions:

shmfdAd.png

23 hours ago, MarkE said:

Unfortunately, it seems you still need the php template file, even if empty. It would be nice to get rid of that...

You can even do that. Not sure if that's something that should be added to RockFrontend though. I'll add an entry to the WIKI...

Here it is:ย https://github.com/baumrock/RockFrontend/wiki/RockFrontend-and-Markup-Regions#advanced-setup

  • Like 1
Link to comment
Share on other sites

55 minutes ago, gornycreative said:

Might be worth adding a prerequisite to the module requirements - I still had a few sites on PHP 7 and the version of composer you include expects PHP 8 at minimum.

Just letting you know.

Thx I've added PHP>=8.0 to the module requirements array ?ย 

  • Thanks 1
Link to comment
Share on other sites

Latte & RockFrontend make a great combination. I have done a couple of variations: indented repeaters - as per above:

and also a menu which mirrors the page hierarchy (for pages matching a given selector) - I can supply an example if anyone is interested.

I'm now getting to know Alfred ?ย and have a few queries:

  1. Is in-line editing possible?
  2. I have a gallery (using Uikit lightbox). When I use alfred with that - <div uk-lightbox {alfred($page, theme_images)}> - the lightbox is opened when I click the edit button and I have to close it before editing - is there any way round that?
  3. Also, in the gallery, I would like to use alfred to edit the indiviual image <figcaption>. Sort of like
    <figcaption {alfred($img, theme_summary)>{$img->theme_summary}</figcaption>

    but obviously that doesn't work. Any way this is possible?

Many thanks for any suggestions.

Link to comment
Share on other sites

8 hours ago, MarkE said:

Latte & RockFrontend make a great combination.

Thx, I'm also very happy with itย ?

8 hours ago, MarkE said:

and also a menu which mirrors the page hierarchy (for pages matching a given selector) - I can supply an example if anyone is interested.

Sure!

8 hours ago, MarkE said:

I'm now getting to know Alfred ?ย and have a few queries:

  1. Is in-line editing possible?

I don't understand. ALFRED's whole purpose it to have an easy frontend editing interface when inline editing does not work or is not appropriate... What do you mean?

8 hours ago, MarkE said:

I have a gallery (using Uikit lightbox). When I use alfred with that - <div uk-lightbox {alfred($page, theme_images)}> - the lightbox is opened when I click the edit button and I have to close it before editing - is there any way round that?

Yeah that's an issue with UIkit not with ALFRED ?ย But you can customize the toggle of your lightbox, seeย https://getuikit.com/docs/lightbox#component-options

9 hours ago, MarkE said:

Also, in the gallery, I would like to use alfred to edit the indiviual image <figcaption>. Sort of like

<figcaption {alfred($img, theme_summary)>{$img->theme_summary}</figcaption>

but obviously that doesn't work. Any way this is possible?

It's not obvious to me that this does not work. What exactly is wrong? Maybe you are just missing quotes in your alfred call? Or is is the issue with the lightbox that might be solved with the solution I showed above?

Link to comment
Share on other sites

7 hours ago, bernhard said:
16 hours ago, MarkE said:

and also a menu which mirrors the page hierarchy (for pages matching a given selector) - I can supply an example if anyone is interested.

Sure!

I've posted that in the Latte thread since it makes more sense (maybe?) there.ย 

ย 

7 hours ago, bernhard said:

I don't understand. ALFRED's whole purpose it to have an easy frontend editing interface when inline editing does not work or is not appropriate... What do you mean?

Maybe I misunderstood. I see now that alfred is a substitute for Option D only.

7 hours ago, bernhard said:

But you can customize the toggle of your lightbox

Thanks for that - works well.

7 hours ago, bernhard said:

It's not obvious to me that this does not work. What exactly is wrong? Maybe you are just missing quotes in your alfred call? Or is is the issue with the lightbox that might be solved with the solution I showed above?

I get an error "Call to a member function hasField() on null" which seems to be generated from Latte (RuntimeChecker.php line 38). I guess it is something to do with $img being a PageImage class and not a Page. "theme_summary" is a custom image field and I'm struggling finding out how to use a front end editor on those. The image is one of a number in an images field within a repeater, which I guess doesn't make it any easier. Before custom image fields came along, I used to put each image on a page and link to them with a multi-value page ref field - I'm sort-of wishing I'd carried on that way. And BTW, I the lightbox fix doesn't work in this context - the fix I use isย uk-lightbox="toggle: .gallery-item a" but that catches the figcaption too and trying anything more specific messes up the lightbox.

Link to comment
Share on other sites

1 hour ago, MarkE said:

I get an error "Call to a member function hasField() on null" which seems to be generated from Latte (RuntimeChecker.php line 38). I guess it is something to do with $img being a PageImage class and not a Page. "theme_summary" is a custom image field and I'm struggling finding out how to use a front end editor on those. The image is one of a number in an images field within a repeater, which I guess doesn't make it any easier. Before custom image fields came along, I used to put each image on a page and link to them with a multi-value page ref field - I'm sort-of wishing I'd carried on that way. And BTW, I the lightbox fix doesn't work in this context - the fix I use isย uk-lightbox="toggle: .gallery-item a" but that catches the figcaption too and trying anything more specific messes up the lightbox.

Well, that's a totally different story then. Your explanation was a little short, so I did not realise we are talking about a field of an image rather than a field of a page...ย 

I've at least posted an update that forces the first alfred argument to be a Page. And if you provide something else you'll at least get a better error message:

Quote

ProcessWire\RockFrontend::alfred(): Argument #1 ($page) must be of type ?ProcessWire\Page, ProcessWire\Template given

I don't know of any good way to render the editor interface just for one single image (or even a field of that image) so I don't think what you are trying to do is easy to achieve.

  • Like 2
Link to comment
Share on other sites

v2.1.0 adds a totally revamped module config and changes the way some assets are loaded - if you used some RockFrontend magic and notice something is not working any more after upgrade make sure that all necessary features are enabled and all necessary assets are loaded:

NX8WxK9.png

If you find anything that should be added to those settings let me know!

@dotnetic ๐Ÿ˜‰ย 

Link to comment
Share on other sites

  • 2 weeks later...

Hey @bernhard,

after deploying from ddev to a live server Tracy is giving me 3 errors per page load (frontend only) like this:

PHP Warning: is_dir(): open_basedir restriction in effect. File(/) is not within the allowed path(s): (/home/sites/XXXXXXXXXXXX/:/tmp/:/dev/:/usr/share/php/:/etc/ssl/certs/:/usr/lib64/php8.0/bin/) in .../XXXXXXXXXXXXXX/public/wire/core/WireFileTools.php:765

I wasn't even sure if Rockfrontend was the culprit here, but I checked two versions. On 2.0.7 Tracy gave me the error twice, while on 2.1.5 it's three times per page..

We're on a shared hosting plan with this project, not sure how to go about this.. Any idea what could be going on there?

Link to comment
Share on other sites

Hi @bernhardย - a few small things I have noticed.

The site assumes a 'site' root for the site directory, but on multi-site this is often not the case.

Is there a technical reason why you are forcing a base uikit head.css to be injected? Again, this is pulling from the site directory which creates a little confusion on multi-site.

I could shuffle around things with my other stylesheet loads and/or eventually add them to the scripts method, but I am wondering if this is due to a backend switch being flipped or is the default behavior. If I already build from LESS with uikit it seems redundant to load head.css again?

Link to comment
Share on other sites

12 hours ago, Andi said:

Hey @bernhard,

after deploying from ddev to a live server Tracy is giving me 3 errors per page load (frontend only) like this:

PHP Warning: is_dir(): open_basedir restriction in effect. File(/) is not within the allowed path(s): (/home/sites/XXXXXXXXXXXX/:/tmp/:/dev/:/usr/share/php/:/etc/ssl/certs/:/usr/lib64/php8.0/bin/) in .../XXXXXXXXXXXXXX/public/wire/core/WireFileTools.php:765

I wasn't even sure if Rockfrontend was the culprit here, but I checked two versions. On 2.0.7 Tracy gave me the error twice, while on 2.1.5 it's three times per page..

We're on a shared hosting plan with this project, not sure how to go about this.. Any idea what could be going on there?

Hey @Andiย not sure but I think I'd add a bd(Debug::backtrace()); right above WireFileTools.php:765 to see which files are triggering the error, can you try that and see if you find something useful?

  • Like 1
Link to comment
Share on other sites

4 hours ago, gornycreative said:

The site assumes a 'site' root for the site directory, but on multi-site this is often not the case.

Could you please give some more details of where it assumes that and how it should behave?

4 hours ago, gornycreative said:

Is there a technical reason why you are forcing a base uikit head.css to be injected? Again, this is pulling from the site directory which creates a little confusion on multi-site.

Could you please also give me more details here?

4 hours ago, gornycreative said:

I could shuffle around things with my other stylesheet loads and/or eventually add them to the scripts method, but I am wondering if this is due to a backend switch being flipped or is the default behavior. If I already build from LESS with uikit it seems redundant to load head.css again?

Please give me a longer explanation so that I can better understand, thx!

Link to comment
Share on other sites

42 minutes ago, bernhard said:

Hey @Andiย not sure but I think I'd add a bd(Debug::backtrace()); right above WireFileTools.php:765 to see which files are triggering the error, can you try that and see if you find something useful?

Hey and thanks. So that gives me 5 dumps, 3 of which look similar to this one

array
	0 => 
		array
        'file' => '/site/modules/RockFrontend/AssetsArray.php:69'
        'call' => 'WireFileTools $files->find("/", [ 2, array(2) ])'   <--- this seems to be causing trouble
	1 => 
		array
          'file' => '/site/modules/RockFrontend/StylesArray.php:28'
          'call' => 'StylesArray->addAll(false, "", 2, [ 'css', 'less' ])'
    2 => 
        array
        'file' => '/site/modules/RockFrontend/RockFrontend.module.php:513'
        'call' => 'StylesArray->addAll("/site/templates/layouts")'
    3 => 
	    array
			'file' => '/site/modules/RockFrontend/RockFrontend.module.php:266'
    		'call' => '$rockfrontend->autoload(Page $obj)'
    4 => 
	    array
		    'file' => '/wire/modules/Process/ProcessPageView.module:184'
    		'call' => 'Page $settings->render()'
    5 => 
	    array
			'file' => '/wire/modules/Process/ProcessPageView.module:114'
			'call' => 'ProcessPageView $process->renderPage(Page $obj, PagesRequest $obj)'
    6 => 
	    array
			'file' => '/index.php:55'
			'call' => 'ProcessPageView $process->execute([ true ])'

The other ones look like this

0 => 
	array
		'file' => '/site/modules/RockFrontend/AssetsArray.php:69'
		'call' => 'WireFileTools $files->find("/home/sites/XXXXX/web/XXXXXX/public/site/templates/sections/", [ 2, array(2) ])'

...

So somehow AssetsArray.php seems to be looking for something in the server root, although I have no idea what exactly, and why ๐Ÿ˜„

I'll investigate further.. Many thanks for the pointers @bernhard

Link to comment
Share on other sites

The issue is most likely RockFrontend->getPath() not returning the correct path for your setup. Can you check this: Add 2 bd() calls in AssetsArray::addAll

  /**
   * Add all files of folder to assets array
   *
   * Depth is 2 to make it work with RockPageBuilder by default.
   *
   * @return self
   */
  public function addAll($path, $suffix = '', $levels = 2, $ext = ['js'])
  {
    /** @var RockFrontend $rf */
    $rf = $this->wire('modules')->get('RockFrontend');
    bd($path, 'before');
    $path = $rf->getPath($path);
    bd($path, 'after');
    $files = $this->wire->files->find($path, [
      'recursive' => $levels,
      'extensions' => $ext,
    ]);
    foreach ($files as $f) $this->add($f, $suffix);
    return $this;
  }

The output should look something like this:

DT6HCyc.png

  • Like 1
Link to comment
Share on other sites

Ok so a little more info.. It seems RF is trying to add styles from

StylesArray->addAll("/site/templates/layouts")

Although I'm currently not using layouts on the site.

Then also from

StylesArray->addAll("/site/assets/RockMatrix")

and

StylesArray->addAll("/site/assets/RockPageBuilder")

which I don't have installed on this setup, maybe that helps...

Link to comment
Share on other sites

21 minutes ago, bernhard said:

The output should look something like this:

before
'/site/templates/layouts'
after
false

before
'/site/templates/sections'
after
'/home/sites/XXXXXXX/public/site/templates/sections/'

before
'/site/templates/partials'
after
'/home/sites/XXXXXXX/public/site/templates/partials/'

before
'/site/assets/RockMatrix'
after
false

before
'/site/assets/RockPageBuilder'
after
false
Link to comment
Share on other sites

Sorry @Andiย just pushed another fix in v2.1.10 - that should work!

Though I'd be interested why it is trying to access something in /

Could you do a bd($dir) aboveย https://github.com/baumrock/RockFrontend/blob/5a9ee3ab7d78481ba2bfecb81c03d32556476525/RockFrontend.module.php#L838 and let me know what dirs it tries to access?

Link to comment
Share on other sites

12 minutes ago, bernhard said:

Could you do a bd($dir) aboveย https://github.com/baumrock/RockFrontend/blob/5a9ee3ab7d78481ba2bfecb81c03d32556476525/RockFrontend.module.php#L838 and let me know what dirs it tries to access?

Error is still there on 2.1.10 unfortunately.. Here's the bd..

I need to run now but I'll happily provide more information later today.

'/home/sites/XXXXXXXXX/public/site/templates/site/templates/layouts'

'/home/sites/XXXXXXXXX/public/site/assets/site/templates/layouts'

'/home/sites/XXXXXXXXX/public/site/templates/layouts'

'/home/sites/XXXXXXXXX/public/site/templates/site/templates/sections'

'/home/sites/XXXXXXXXX/public/site/assets/site/templates/sections'

'/home/sites/XXXXXXXXX/public/site/templates/sections'

'/home/sites/XXXXXXXXX/public/site/templates/site/templates/partials'

'/home/sites/XXXXXXXXX/public/site/assets/site/templates/partials'

'/home/sites/XXXXXXXXX/public/site/templates/partials'

'/home/sites/XXXXXXXXX/public/site/templates/site/assets/RockMatrix'

'/home/sites/XXXXXXXXX/public/site/assets/site/assets/RockMatrix'

'/home/sites/XXXXXXXXX/public/site/assets/RockMatrix'

'/home/sites/XXXXXXXXX/public/site/templates/site/assets/RockPageBuilder'

'/home/sites/XXXXXXXXX/public/site/assets/site/assets/RockPageBuilder'

'/home/sites/XXXXXXXXX/public/site/assets/RockPageBuilder'

Thanks a bunch!

  • Like 1
Link to comment
Share on other sites

Meanwhile we have a great new feature: You can now simply paste a google fonts url into the module settings and RockFrontend will automatically download all files to /site/templates/fonts (this is not new) and (this is new) also create the file /site/templates/fonts/webfonts.css and add this file to the sites' styles array.

That means if you need another weight of your font (eg you need Gudea 900) you simply add 900 to the url, hit save and your frontend will have that font availableย ๐Ÿ˜Ž

NOFhDvq.png

I realised that before this update there were still some steps required with the old webfont downloader to copy and paste the whole CSS to the correct file etc etc... Now RockFrontend does all that for you ๐Ÿ™‚ย 

  • Like 3
Link to comment
Share on other sites

4 hours ago, bernhard said:

Though I'd be interested why it is trying to access something in /

So, back on this.

If I create an empty folder "site/templates/layouts", there's only two errors coming up..

So I guess for the 3 directories that do not exist, instead of not doing anything, the script somehow falls back to trying to look up files in the server root

'/site/templates/layouts' 		<-- does not exist, error 1
'/site/templates/sections' 		<-- exists
'/site/templates/partials' 		<-- exists
'/site/assets/RockMatrix' 		<-- does not exist, error 2
'/site/assets/RockPageBuilder' 	<-- does not exist, error 3

Let me know if you need anything else and thanks again! RF is really fantastic already, and loving the new features.

  • Like 1
Link to comment
Share on other sites

  • bernhard changed the title to RockFrontend ๐Ÿš€๐Ÿš€ Take your ProcessWire Frontend Development to the Next Level

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
ร—
ร—
  • Create New...