Post by Lumirion » Fri Apr 19, 2024 1:53 am

Looking through twig files like Product.twig and contact.twig I see a variable at the top that looks like this {{ header }} . I would like to add custom styles and scripts to particular views with out affecting other views that use the same headers. Is it possible to make a local copy of the contents of the {{ header }} and insert my changes into the copy like a string variable before before adding it to the twig like {{ HeaderCopy }} ? Or is there a more correct way to do this in OC 3?
Last edited by Lumirion on Thu May 09, 2024 5:58 am, edited 1 time in total.

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by straightlight » Fri Apr 19, 2024 8:14 am

Lumirion wrote:
Fri Apr 19, 2024 1:53 am
Looking through twig files like Product.twig and contact.twig I see a variable at the top that looks like this {{ header }} . I would like to add custom styles and scripts to particular views with out affecting other views that use the same headers. Is it possible to make a local copy of the contents of the {{ header }} and insert my changes into the copy like a string variable before before adding it to the twig like {{ HeaderCopy }} ? Or is there a more correct way to do this in OC 3?
OC version. There are multiple ways you could achieve this:

- By layouts
- By extension modules
- By event triggers

without the need to reproduce the header content since OC uses the top, left, right and bottom directions to load contents from the core already.

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by Lumirion » Sat Apr 20, 2024 5:23 am

I'm using Opencart 3. I would like to use the event system to do this because I like the idea of a clean core. How do I get my event to put my code into the head tag only when my chosen view is is being generated?

Code: Select all

 
/* before */
public function addStylesAndScriptsToProductPages(&$route, &$args) {
    /*
        the Product route is 'product/product', 
        aka: 'catalog/view/theme/journal3/template/product/product.twig'
    */
    if ($route == 'product/product') {
        /*
           What do I do here to get my code into the head section
        */
    }
}

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by halfhope » Sat Apr 20, 2024 5:38 am

Hi!

You may use my extension Custom Templates Pro for this. This extension can substitute any template file (twig) in the engine for any route, and more.

Unfortunately, right now demo sites are unavailable.

My FREE extensions in marketplace. [ security | flexibility | speedup ]


User avatar
Active Member

Posts

Joined
Tue Dec 10, 2013 9:44 pm
Location - San Diego

Post by straightlight » Sat Apr 20, 2024 9:54 am

Lumirion wrote:
Sat Apr 20, 2024 5:23 am
I'm using Opencart 3. I would like to use the event system to do this because I like the idea of a clean core. How do I get my event to put my code into the head tag only when my chosen view is is being generated?

Code: Select all

 
/* before */
public function addStylesAndScriptsToProductPages(&$route, &$args) {
    /*
        the Product route is 'product/product', 
        aka: 'catalog/view/theme/journal3/template/product/product.twig'
    */
    if ($route == 'product/product') {
        /*
           What do I do here to get my code into the head section
        */
    }
}
Take note that Journal framework is not supported on the forum. However, according to your event trigger code, you are using a /before event as your comment specifies that you're looking to target the product/product.twig file. Therefore, you'd need to use a /after event to achieve this.

Multiple examples on how to achieve this can be looked into your catalog/controller/extension/advertise/google.php file . Alternatively, you can also look for the codes:

Code: Select all

$this->document->addStyle

$this->document->addScript
in the core which should automatically add your CSS and JS codes accordingly into the header.

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by Lumirion » Mon Apr 22, 2024 11:35 pm

Ah! I see. I was operating under the assumption that I could change the twig input prior to generating the HTML with the before event. But an after event should work just as well for my purposes. Thanks for the URL for the google controller, I think that implementation will be quite informative. Journal’s lack of support her is duly noted. Personally, I’d like to learn OpenCart well enough that I can ignore Journal as much as possible. I'll give this a try and pop back if I get stuck. Thank you all for the helpful suggestions.

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by Lumirion » Fri Apr 26, 2024 12:27 am

I tried following this guide https://github.com/osworx/opencart-even ... me-ov-file to install my event. I created a folder with the following structure inside it:
upload\catalog\controller\event\Insert_PDP_StylesAndScripts.php. In the top level, next to upload, I put a file called install.json. Then I zipped the top level folder into a file named Insert_PDP_StylesAndScripts.ocmod.zip. On the backend of a test site, I went to Extensions->Installer and clicked upload. The file uploaded and I got the Install successful message. But I don’t see my module under Extensions->Modules or my event under Events. My Insert_PDP_StylesAndScripts.php looks like this

Code: Select all

<?php
class ControllerEventInsertPDPStylesAndScripts extends Controller {
	public function install() {
		$this->load->model('setting/event');
		$this->model_setting_event->deleteEventByCode('Insert_PDP_StylesAndScripts');
		if($this->request->post['module_Insert_PDP_StylesAndScripts_status']){
			$this->model_setting_event->addEvent('Insert_PDP_StylesAndScripts', 'catalog/view/theme/journal3/template/product/product/after', 'controller/event/Insert_PDP_StylesAndScripts/addStylesAndScriptsToProductPages');
		}
	}
	public function uninstall(){
		$this->load->model('setting/event');
		$this->model_setting_event->deleteEventByCode('Insert_PDP_StylesAndScripts');
	}
	/* After product.twig is converted to HTML inject our CSS and styles into head */
	public function addStylesAndScriptsToProductPages(&$route, &$args, &$output) {
		/*
			if the view route is 'product/product',
			aka: 'catalog/view/theme/journal3/template/product/product.twig'
		*/
		if ($route == 'product/product') {
			/* replace the </head> with the Styles and scripts we want */
			$output = str_replace('</head>', '<style>

		/* For mobile Devices: */
		.desktoplogo {
			display: none;
		}
		.mobilelogo {
			display: block;
		}
		/* For PC */
		@media only screen and (min-width: 768px) {
			.mobilelogo {
				display: none;
			}
			.desktoplogo {
				display: none;
			}
		}

		</style>
		</head>', $output);
		}
	}
}
Anyone have an idea what I did wrong?

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by Lumirion » Fri May 03, 2024 4:13 am

I created a clean testing environment by installing the latest 3.0.3.9 version of OpenCart on a Virtual machine. Then I made a basic module and tested whether it would install on the server. I removed the module and edited it to register an event and handle it like this:

Code: Select all

public function install() {
	$this->load->model('setting/event');
	$this->model_setting_event->deleteEventByCode('Insert_PDP_StylesAndScripts');
	if(!$this->model_setting_event->getEventByCode('Insert_PDP_StylesAndScripts')){ /* No copies of this event, or older versions, are still loded. Its safe to load one. */
		$this->model_setting_event->addEvent('Insert_PDP_StylesAndScripts', 'catalog/view/product/product/after', 'extension/module/Insert_PDP_StylesAndScripts/addStylesAndScriptsToProductPages');
		}
}
public function uninstall(){
	$this->load->model('setting/event');
	$this->model_setting_event->deleteEventByCode('Insert_PDP_StylesAndScripts');
}

/* After product.twig is converted to HTML inject our CSS and styles into head */
public function addStylesAndScriptsToProductPages(&$route, &$args, &$output){
	/* replace the </head> with the Styles and scripts we want */
	$output = str_replace('</head>', '<style>

		/* For mobile Devices: */
		.PClayout {
			display: none;
		}
		.MobileLayout {
			display: block;
		}
		/* For PC */
		@media only screen and (min-width: 768px) {
			.MobileLayout {
				display: none;
			}
			.PCLayout {
				display: block;
			}
		}

		</style>
		</head>', $output);
    }
}
When I install the module the event is registered but after clearing all the caches and navigating to a default OpenCart product page if I inspect the html source the head tag remains empty.

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by straightlight » Fri May 03, 2024 6:13 am

Lumirion wrote:
Fri May 03, 2024 4:13 am
I created a clean testing environment by installing the latest 3.0.3.9 version of OpenCart on a Virtual machine. Then I made a basic module and tested whether it would install on the server. I removed the module and edited it to register an event and handle it like this:

Code: Select all

public function install() {
	$this->load->model('setting/event');
	$this->model_setting_event->deleteEventByCode('Insert_PDP_StylesAndScripts');
	if(!$this->model_setting_event->getEventByCode('Insert_PDP_StylesAndScripts')){ /* No copies of this event, or older versions, are still loded. Its safe to load one. */
		$this->model_setting_event->addEvent('Insert_PDP_StylesAndScripts', 'catalog/view/product/product/after', 'extension/module/Insert_PDP_StylesAndScripts/addStylesAndScriptsToProductPages');
		}
}
public function uninstall(){
	$this->load->model('setting/event');
	$this->model_setting_event->deleteEventByCode('Insert_PDP_StylesAndScripts');
}

/* After product.twig is converted to HTML inject our CSS and styles into head */
public function addStylesAndScriptsToProductPages(&$route, &$args, &$output){
	/* replace the </head> with the Styles and scripts we want */
	$output = str_replace('</head>', '<style>

		/* For mobile Devices: */
		.PClayout {
			display: none;
		}
		.MobileLayout {
			display: block;
		}
		/* For PC */
		@media only screen and (min-width: 768px) {
			.MobileLayout {
				display: none;
			}
			.PCLayout {
				display: block;
			}
		}

		</style>
		</head>', $output);
    }
}
When I install the module the event is registered but after clearing all the caches and navigating to a default OpenCart product page if I inspect the html source the head tag remains empty.
Did you used the installer with your ZIP file to run this extension? You'll need to post the complete ZIP file to take a look.

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by Lumirion » Fri May 03, 2024 10:37 pm

Yes, I used the installer. Here is a copy of the zip. https://drive.google.com/file/d/1QN76K ... p=sharing

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by straightlight » Sat May 04, 2024 2:15 am

Lumirion wrote:
Fri May 03, 2024 10:37 pm
Yes, I used the installer. Here is a copy of the zip. https://drive.google.com/file/d/1QN76K ... p=sharing
Two issues:

Code: Select all

$this->model_setting_event->addEvent('Insert_PDP_StylesAndScripts', 'catalog/view/product/product/after', 'extension/module/Insert_PDP_StylesAndScripts/addStylesAndScriptsToProductPages');
1 - You're targeting the catalog/view/product/product/after route but you're looking to modify the <head> portion which would be the wrong location from your event code.

2 - You're using uppercase letters and underscores with your extension/module/Insert_PDP_StylesAndScripts/addStylesAndScriptsToProductPages compared to your controller conventional name. Best to rename your filenames all lowercase as well as your controller routes by also removing the underscores from your routes.

3 (optional but good to know): You're using:

Code: Select all

<!--
and:

Code: Select all

-->
The TWIG engine allows the use of:

Code: Select all

{#
and:

Code: Select all

#}

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by Lumirion » Sat May 04, 2024 3:40 am

Good point about removing the underscores and capitalization in my routes and filenames. I will rename the files and update routes and fix the twig syntax shortly.
Now about my product page route, I’m trying to edit the head only when it’s being used for a product page. I don’t think that, if I use the header route, I can tell from the header controller which page is currently using it.
So would it be better to create a new view that extends header.twig and use my current route to the product page to over write {header} ? Or is there a simpler way?

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by straightlight » Sat May 04, 2024 4:25 am

Lumirion wrote:
Sat May 04, 2024 3:40 am
Good point about removing the underscores and capitalization in my routes and filenames. I will rename the files and update routes and fix the twig syntax shortly.
Now about my product page route, I’m trying to edit the head only when it’s being used for a product page. I don’t think that, if I use the header route, I can tell from the header controller which page is currently using it.
So would it be better to create a new view that extends header.twig and use my current route to the product page to over write {header} ? Or is there a simpler way?
Using the /after trigger, the &$route string will already determine the location. Therefore, you could still use:

Code: Select all

$this->request->get['route']
vs. &$route in your event controller extension file targeted for header.twig file. You could compare and test both routes from your catalog/controller/event/debug.php file on a test environment.

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by straightlight » Sat May 04, 2024 4:28 am

Alternatively, since you are targeting the catalog product page, you could also create a new design layout and add the desired HTML / CSS code in your layout since you are also creating an extension in the extension/module folder in this scenario.

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by Lumirion » Mon May 06, 2024 10:36 pm

Thank you. Ill switch to modifying the header and use

Code: Select all

 $this->request->get['route'] 
to compare against the route to the product page. If that route is for the product page then I'll insert my styles.

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by Lumirion » Tue May 07, 2024 6:01 am

I made the changes we discussed. I changed the route registered in the event to 'catalog/view/common/header/after', and I modified the event handler like this.

Code: Select all

 
                /* After product.twig is converted to HTML inject our CSS and styles into head */
	public function addproductpagestyles(string &$route, array &$args, mixed &$output): void {
        /* Get the route of the current page this header is being used on and see if it is a product page. */
        if (str_contains($this->request->get['route'], 'product/product')) {
            /* replace the </head> with the Styles and scripts we want */
            $output = str_replace(['</head>'], '<style>

            /* For mobile Devices: */
            .PClayout {
                display: none;
            }
            .MobileLayout {
                display: block;
            }
            /* For PC */
            @media only screen and (min-width: 768px) {
                .MobileLayout {
                    display: none;
                }
                .PClayout {
                    display: none;
                }
            }

            </style>
            </head>', $output);
        }
    }
Here is a link to the entire extension. https://drive.google.com/file/d/1xQMIma ... sp=sharing

It seems to be running and trying to affect the product pages, but the style sample is not in the head element. Instead, an error message pops up on product pages.
It says ” Unknown: preg_replace(): Passing null to parameter #3 ($subject) of type array|string is deprecated in /var/www/html/opencart/storage/modification/system/engine/action.php on line 65”
Do I need to do something to $output before str_replace?

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by straightlight » Tue May 07, 2024 11:16 pm

You are still targeting product/product with </head> . As per my previous reply, you need to target the common/header TWIG file for that. Otherwise, you could also use:

Code: Select all

$this->document->addStyle
instead of manually adding the code into the str_replace . The style code would then load specifically when the product/product route would be loaded in this case. In the str_replace, you don't need to use an array, since you're looking for a string type, which in this case, the string type is irrelevant on product/product as it is nowhere to be found on that file.

You don't need to use: str_contains to track the route. Simply:

Code: Select all

if (isset($this->request->get['route']) && $this->request->get['route'] == 'product/product') {
...
}
would suffice to validate the route. Take note that if you were to target the common/home route, the route from the super global would not be identifiable since the framework system already assumes that the common/home is the priority route of the platform when the maintenance mode is not enabled.

As for the deprecation error message, you mentioned to use Opencart 3 but the 4 decimal version hasn't been provided on your behalf.

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by Lumirion » Wed May 08, 2024 12:37 am

I’m using PHP 8.2 and Opencart 3.0.3.9 downloaded on 4/29/2024.
Line 22 of insertproductpagesstyles.php, targeting the product page is commented out. Line 23 looks like this.

Code: Select all

$this->model_setting_event->addEvent('insertproductpagestyles', 'catalog/view/common/header/after', 'extension/module/insertproductpagestyles/addproductpagestyles');
It should be targeting the header, then checking if the header is being used for a product page. I will remove the array indicators around the search string.
I will switch to the safer route check. I will definitely look into using $this->document->addStyle but I also want to get this version running as well .

If I were to switch to the Product/product route and replace the str_replace with a $this->document->addStyle would the route designation from the event be sufficient to associate the “$this” with the product page?

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by straightlight » Wed May 08, 2024 3:47 am

Lumirion wrote:
Wed May 08, 2024 12:37 am
I’m using PHP 8.2 and Opencart 3.0.3.9 downloaded on 4/29/2024.
Line 22 of insertproductpagesstyles.php, targeting the product page is commented out. Line 23 looks like this.

Code: Select all

$this->model_setting_event->addEvent('insertproductpagestyles', 'catalog/view/common/header/after', 'extension/module/insertproductpagestyles/addproductpagestyles');
It should be targeting the header, then checking if the header is being used for a product page. I will remove the array indicators around the search string.
I will switch to the safer route check. I will definitely look into using $this->document->addStyle but I also want to get this version running as well .

If I were to switch to the Product/product route and replace the str_replace with a $this->document->addStyle would the route designation from the event be sufficient to associate the “$this” with the product page?

Code: Select all

$this->document->addStyle(...);
can be used on any extensions whether it's OCMod or Event Triggers. There's no need to use a $data array nor the $output to call the $this->document library object. Prior to the output being used back on the OC Engine, library objects can be imported independently.

Dedication and passion goes to those who are able to push and merge a project.

Regards,
Straightlight
Programmer / Opencart Tester


Legendary Member

Posts

Joined
Mon Nov 14, 2011 11:38 pm
Location - Canada, ON

Post by Lumirion » Thu May 09, 2024 12:17 am

Ok. Just as a test I switched the route back to the product page and replaced my str_replace with

Code: Select all

 $this->document->addStyle('catalog/view/PDPStyles/productpage.css');  
and added that css file with my styles in it. The result is the same error about preg_replace being passed a NULL as the third value in line 65 of action.php. My css is not inserted into the product page either. Line 65 of action.php

Code: Select all

 $class = 'Controller' . preg_replace('/[^a-zA-Z0-9]/', '', $this->route); 
seems to be assembling the route to my insertproductpagestyles.php at admin/controller/extension/module/. $this->route seems to be returning null, so my controller is not referenced and my event handler is not called. Is there something wrong with either of these two addEvent lines?

Code: Select all

 $this->model_setting_event->addEvent('insertproductpagestyles', 'catalog/view/common/header/after', 'extension/module/insertproductpagestyles/addproductpagestyles'); 
and

Code: Select all

 $this->model_setting_event->addEvent('insertproductpagestyles', 'catalog/view/product/product/after', 'extension/module/insertproductpagestyles/addproductpagestyles'); 
Is it trying to look for my controller in catalog/controller/extension/module/ instead of in admin/controller/extension/module/ ?
Edit- Apparently it was. I added a new controller file insertproductpagestyles.php in catalog/controller/extension/module/ containing my event handler. Currently I no longer see that error message, but my

Code: Select all

 $this->document->addStyle('catalog/view/PDPStyles/productpage.css');  
isn't doing anything. So I will switch back to modifying the header.
Last edited by Lumirion on Thu May 09, 2024 2:40 am, edited 1 time in total.

New member

Posts

Joined
Fri Apr 19, 2024 1:32 am
Who is online

Users browsing this forum: No registered users and 8 guests