Jump to content

Custom Page Class not being assigned


MarkE
 Share

Recommended Posts

Posted (edited)

I have a template Motif-sub-layout and a Page Class MotifSubLayoutPage. In my dev setup, the page class is correctly assigned to the template:

190162807_Screenshot2024-05-18111436.png.b0247fcc2d64046f2d91c98f4e3ab699.png

However in the live enmvironment it is assigned to just the 'Page' class:

373875217_Screenshot2024-05-18111357.png.ff703ceee680621b2d8796a3d22597ee.png

The environments have exactly the same code, exactly the same database and are both on PW3.0.229 and PHP8.1.

I checked my config.php and can't see any differences in the live and dev settings that would cause the problem. $config->usePageClasses = true; is set in both environments.

Any ideas???

Further info in case it's relevant:

I have a whole bunch of Page Classes within my site/classes/ directory. These all work in both environments. MotifSubLayoutPage is one of about 20 page classes included in a script 'MotifBlockPage.class.php' which is included via init() in an autoloaded module - all the other page classes in this script work fine in both environments. As illustrated above, MotifSubLayoutPage works ok in the dev, but not in the live although the code and databases are identical. 😔

And:

via a bd in Tracy, I can see that the Motif-sub-layout template has a filename property 'site/templates/Motif-sub-layout.php' but that file does not exist and looking at the template via the UI does not disclose and linked filename. The other templates do not seem to have the property set (i.e. filename is null). However, if I inspect the template info directly on the template edit page, it gives 'No file' for filename in all cases. Is that a clue? Executing d($t->filename); in the Tracy command window does generate a (non-existent) file name in all cases, which I guess is just what it is looking for if it needs to render something, so this may be irrelevant info!

UPDATE:

I have a partial work-round fix. In fact there are 3 templates which are not picking up the correct custom page class. I can't see anything unusual about them (and they all work in the dev environment). As a work-round, I have 'manually' added the correct PageClass on the system tab of the template edit page. This 'fixes' most of the error, but there is one page which uses one of those templates where it is still not picking up the right class.

Edited by MarkE
Update
Link to comment
Share on other sites

Thanks @Andi. I just added an update to my post while you were replying, although I don't know that it sheds much more light on it. I'm normally a bit nervous about installing dev version on my live sites but, in this case, since the problem is breaking my site, I may have to go with it (I can't test that the dev version fixes the problem by testing on my dev site as the error doesn't happen there 🙄)

Link to comment
Share on other sites

Hey @MarkE, I know the feeling 🙂 If you want to make absolutely sure, I'd suggest making a Duplicator copy of the entire site, install it on your live environment, using a subdomain and a different database.. Then update that site and see if it fixes things..

Just don't get confused with the different installations 😄

  • Like 1
Link to comment
Share on other sites

Posted (edited)

Recap: I have a work-round that works in almost all cases, although it is unsatisfactory in that it doesn't fix the underlying problem (...see later in this post).

I have one situation where even the work-round is not working: I have a template called MotifDisplay with a page class MotifDisplayPage. 'MotifDisplayPage.class.php' is included via a call from init() in an autoloaded module thus:

		require_once($this->modulePath . 'MotifPage.class.php');
		require_once($this->modulePath . 'MotifLayoutPage.class.php');
		require_once($this->modulePath . 'MotifDisplayPage.class.php');
		require_once($this->modulePath . 'MotifBlockPage.class.php');
		require_once($this->modulePath . 'MotifWidgetPage.class.php');

This all works fine in the dev environment which has the same code and database. In the live environment, the MotifDisplayPage class is not applied, but all the others in the above snippet (and all those in the classes directory) are applied correctly (except for 2 in the MotifBlockPage.class.php script, which has about 20 page classes all structured similarly) . MotifDisplayPage extends MotifLayoutPage which extends MotifPage.

The work-round is to add the page class in the system tab of the MotifDisplay edit page. For all but one pages with the MotifDisplay template, this work-round applies the custom page class correctly. However, one page (with the template MotifDisplay) only gets the Page class, not the MotifDisplayPage class. You can see the effect of this (if you are interested 😉) by going to https://www.ncorchards.co.uk/. All of the pages on the main menu (and footer menu) work, except for 'My NCOG'. They all have the same MotifDisplay template. My Tracy logs show that the 'My NCOG' page has the correct template, but is the only page to have the wrong class*.

As mentioned earlier, the work-round is unsatisfactory in that it doesn't fix the underlying problem. There seems to be no rhyme or reason why just 3 templates are affected and then only on the live site. Even if I could get the work-round to work on all pages, without knowing the cause of the problem, how do I know which templates it might strike next?!

Any thoughts anyone has would be much appreciated because, as you can see, it has broken an important part of the site (the member access portal).

*EDIT: Doing a Tracy dump of $class = $templates->getPageClass($page->template) however yields MotifDisplayPage! See below:

1097639106_Screenshot2024-05-18181848.thumb.png.0e89c2f415665bff4984e3dfe0424a9e.png

Edited by MarkE
More info
Link to comment
Share on other sites

14 hours ago, MarkE said:

*EDIT: Doing a Tracy dump of $class = $templates->getPageClass($page->template) however yields MotifDisplayPage! See below:

 

Perhaps it's not that it "does not get assigned" at all, but rather that it isn't assigned when your code expects it to be, because it hasn't been assigned yet?

  • Like 1
Link to comment
Share on other sites

1 hour ago, szabesz said:

Perhaps it's not that it "does not get assigned" at all, but rather that it isn't assigned when your code expects it to be, because it hasn't been assigned yet?

Than can sometimes be the case, I agree - I've had that before. However that doesn't explain why, in this case, some templates work and others don't when being processed by the same code, nor why one page doesn't work when it uses the same template as other pages and the code processing it is identical. Nor why it works in dev but not live.

  • Like 1
Link to comment
Share on other sites

Unfortunately I have no idea what could be the issue. The only thing that looks weird to me is the capital M in the template name Motif-sub-layout. I'm never using capital letters here, although I know they are allowed - so it might be totally only a personal preference and nonsense in this context. Just wanted to mention that this might be worth testing - maybe your local dev file system is not case sensitive and your remote one is, or similar? I don't know, but it might be worth a try 🙂 Good luck!

Other than that I'd try to revert as much as possible on the remote (maybe remove or uncomment almost anything in the pageclass) and try to see if it works at some point. If so, then jackpot, then you can add things back in and see when it starts to break.

  • Like 1
Link to comment
Share on other sites

1 hour ago, bernhard said:

The only thing that looks weird to me is the capital M in the template name Motif-sub-layout.

I've often done that with templates (habit from early days with PW, so I could easily distiguish template and field names) without problems. The system was working fine with those template names until I changed some legacy custom page classes which I had 'included' via config.php to use the 'new' $config->usePageClasses = true; - this involved adding 'Page' to the end of the file names and classes. All of those work correctly! It's (some of ) the classes that were being added via an include in my module init() that have stopped working (and just on the live site), even though I did not change those!

FWIW, this problem happened after my hosting service had a major SQL corruption problem which caused sites to be down for some time until they restored from a backup. However I checked the site after that problem and before I made the changes and everything seemed OK.

1 hour ago, bernhard said:

Other than that I'd try to revert as much as possible on the remote

I can do this for the site as a whole using cPanel's JetBackup. But that is a last resort as it undoes the improvements I was trying to make.

Before that, I was going to try catching the pages before rendering them and changing the class, if wrong, using reflectionObject() - see code below - although that is a hack and doesn't fix the underlying problem.

	/**
	 * Class casting
	 *
	 * @param string|object $destination
	 * @param object $sourceObject
	 * @return object
	 */
	public static function cast($sourceObject, $destination) {
		if(is_string($destination)) {
			 $destination = new $destination(); // or replace by below to avoid calling constructor
//			$destination = (new \ReflectionClass($destination))->newInstanceWithoutConstructor();
		}
		$sourceReflection = new \ReflectionObject($sourceObject);
		$destinationReflection = new \ReflectionObject($destination);
		$sourceProperties = $sourceReflection->getProperties();
		foreach($sourceProperties as $sourceProperty) {
			$sourceProperty->setAccessible(true);
			$name = $sourceProperty->getName();
			$value = $sourceProperty->getValue($sourceObject);
			if($destinationReflection->hasProperty($name)) {
				$propDest = $destinationReflection->getProperty($name);
				$propDest->setAccessible(true);
				$propDest->setValue($destination, $value);
			} else {
				$destination->$name = $value;
			}
		}
		return $destination;
	}

 

Link to comment
Share on other sites

In case anyone is interested ( @Andi, @szabesz, @bernhard?) I may have found a (sort of) solution to this. As I said 

42 minutes ago, MarkE said:

It's (some of ) the classes that were being added via an include in my module init() that have stopped working (and just on the live site), even though I did not change those!

I moved the include (actually require_once) to config.php rather than in init() and that seems to fix it (still testing...). Though why it was working before when called from init() but not now, I do not know.

Also, I really want to call the includes from my module as the custom pages are module-specific - I don't want them hanging out in config.php. Any ideas?

Link to comment
Share on other sites

2 hours ago, szabesz said:

did you also try it with a different PHP version? Newer or older main PHP version?

Dev and live are both on 8.1

I've now put the 'includes' in the module __construct() method rather than init() or config.php. That seems to work. I'll do a sort of mini-tutorial on this.

  • Like 1
Link to comment
Share on other sites

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...