Post by Lumirion » Thu Aug 21, 2025 3:40 am

* My exact OpenCart version: 3.0.3.3
* Deployed locale or live: Live
* Installed/Used Template/Theme: Journal3
* Installed/Used Translation: none
* Servertype (Linux/MS): Linux
* php-Version: I forget. I was told it was the latest version that opencart 3.0.3.3 can use
* MySQL-Version: not sure
* Used Browser: Firefox, Chrome, Brave
* I use CloudFlare (yes/no): no
* I am the only admin (yes/no): no
* Content of error log file (OpenCart/Server): there is no change in the error logs.

Good morning,
I'm trying to make a function that will take a category id and collect all it's parents back to it's root category. I am using ocmod and I can see my code in the copy of catalog.php in the modifications cache. I have cleared and refreshed the caches as I normally do when installing or configuring a mod. Here is my function.

Code: Select all

	public function getCategoryPath($category_id) {
		$query = $this->db->query("SELECT parent_id FROM " . DB_PREFIX . "category WHERE category_id = '" . (int)$category_id . "'");
		if($query->row['category_id']){ //if this category exists start the path with it
			$CategoryPath = (string)$query->row['category_id'];
			//get current Category's parrents and add them to the begining of the path till we hit root
			while($query->row['parent_id'] > 0) { //If we just added the root to the path we are done
				$query = $this->db->query("SELECT parent_id FROM " . DB_PREFIX . "category WHERE category_id = '" . (int)$query->row['parent_id'] . "'");
				$CategoryPath = $query->row['parent_id'] . "_" . $CategoryPath;
			}
			return $CategoryPath;
		}
		return false;
	}
And I call it with a category id for example 265, which I know exists and has parents. The resulting category path is not used for anything, at the moment. I’m just trying to Log it and see what comes out. I call it like this.

Code: Select all

							$canonical_path = this->getCategoryPath(265);
							$this->log = new \Log('MyCatalogPath.log');
							$this->log->write("The Canonical path for category id 265" . " is " . $canonical_path);
The result is all public facing pages are blank white and no output is logged.

Additionally, in the catalog.php controller when I try to log variables even without calling my function nothing is logged and no file is created. When I use logging in some other controllers it works fine but pasting it in this particular one has no effect. I do have multiple error logs but my logged data doesn’t show up in any of them if I log from catalog.php.
Anyone have some ideas where I am going wrong from an OpenCart perspective?.

New member
Online

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by Cue4cheap » Thu Aug 21, 2025 4:21 am

Lumirion wrote:
Thu Aug 21, 2025 3:40 am
The result is all public facing pages are blank white and no output is logged.
If I am reading what you wrote correctly in what I quoted.... Look at your error log. Not your opencart one but the server error log. It reads like you are getting a 500 error so it is not executing your code.

Mike

cue4cheap not cheap quality


Expert Member

Posts

Joined
Fri Sep 20, 2013 4:45 am

Post by Lumirion » Thu Aug 21, 2025 4:59 am

Yes, you are correct. Execution stops when my function is called so the page never gets generated resulting in 500. I'm trying to figure out what is wrong with the function and If possible why logging does nothing when used inside this controller.
I have made other mods that interact with this file in the past where everything but the logging worked fine. No errors no problems but no logs either.

In this case I think I'm stuck in the while loop but I can't tell why.
[Edit] I also tried the following two while loops.

Code: Select all

while($query->row['parent_id'] != 0)
 while($query->row['parent_id'] != "0")

New member
Online

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by Cue4cheap » Thu Aug 21, 2025 8:51 am

And nothing is logged in your server error logs?

cue4cheap not cheap quality


Expert Member

Posts

Joined
Fri Sep 20, 2013 4:45 am

Post by Cue4cheap » Thu Aug 21, 2025 9:02 am

Lumirion wrote:
Thu Aug 21, 2025 4:59 am
In this case I think I'm stuck in the while loop but I can't tell why.
Maybe this will work for you?

Code: Select all

public function getCategoryPath($category_id) {
    if (!is_numeric($category_id) || $category_id <= 0) {
        return '';
    }

    $category_id = (int)$category_id;
    $path = [(string)$category_id];
    $seen_ids = [$category_id];

    while ($category_id > 0) {
        $query = $this->db->query("SELECT parent_id FROM " . DB_PREFIX . "category WHERE category_id = '" . $this->db->escape($category_id) . "'");
        if (!$query->num_rows) {
            break;
        }

        $parent_id = (int)$query->row['parent_id'];
        if (in_array($parent_id, $seen_ids)) {
            break;
        }

        if ($parent_id > 0) {
            $path[] = (string)$parent_id;
            $seen_ids[] = $parent_id;
            $category_id = $parent_id;
        } else {
            break;
        }
    }

    return implode('_', array_reverse($path));
}

cue4cheap not cheap quality


Expert Member

Posts

Joined
Fri Sep 20, 2013 4:45 am

Post by khnaz35 » Thu Aug 21, 2025 9:13 pm

How about trying in index method of your controller to start ruling out

Code: Select all

$this->log->write('My controller is being called!');
The slowly move to the function?

Got a burning question at 3 AM that even Google shrugs at? There’s a not-so-secret inbox that might just have your answer: khnaz35@gmail.com
Breathe in some nature while you're at it. It’s cheaper than therapy. :-*

Feel free to sling a bear my way via PayPal @ khnaz35@gmail.com


User avatar
Active Member
Online

Posts

Joined
Mon Aug 27, 2018 11:30 pm
Location - Malaysia

Post by Lumirion » Fri Aug 22, 2025 2:22 am

Hi, Thanks for the suggestions. @Cue4cheap - The function you provided produced identical results to my own. There is no change in the error logs I have access to. I checked the log folder and the server root folder. Are there any other locations I can check for logs?
@khnaz35 - I tried your suggestion as well but there was no out put.

New member
Online

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by Lumirion » Fri Aug 22, 2025 3:30 am

Is it likely that a controller is the wrong context to put the function in? Maybe there is a required model for doing queries and logging. Should this function be moved to a model? Maybe the category model?
The models that are loaded are :

Code: Select all

		$this->load->model('catalog/category');
		$this->load->model('catalog/manufacturer');
		$this->load->model('catalog/product');
		$this->load->model('journal3/category');
		$this->load->model('journal3/product');

New member
Online

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by OSWorX » Fri Aug 22, 2025 5:17 am

It's going to be a long story if no further infos are given!

1. which server administration tool are you using (e.g. cPanel/Plesk/Webmin/Other):
2. is error_reporting enabled (see php.ini)
3. add this to your index.php after the opening <?php

Code: Select all

error_reporting( E_ALL );
ini_set( 'error_reporting', E_ALL );
ini_set( 'display_errors', 'On' );
Now you should see IN THE error logfile what's happening.

To enhance this a bit: you are already asked for any error output.
When operating OpenCart you will have at least 1 file with errors - IF enabled in OpenCarts server administration > see Menu System > Setting >> Tab Server >>> Store System messages (or something like that ..).
This must be enabled!

Next is, error_reporting must be enabled on your server (see above).
Or use the lines for the index (catalog and/or admin) from above.

Done until now, and getting an error, you should see that in the error.log (or other name if you have renamed that).

Second is the server error logfile - see for that also above.
Some hoster/provider do not provide settings for that >> change your hoter/provider, he is not worh any money!

There is one major exception: Error 500 means .. everything and nothing.
If 500 is displayed/stored, a hard time is starting, because such errors are really hard to find (could be everything: php, html, twig, jvaascript, server, etc. ).

So please, do your homework and give us more infos - or hire a developer you trust!

Full Stack Web Developer :: Dedicated OpenCart Development & Support DACH Region
Contact for Custom Work / Fast Support.


User avatar
Administrator

Posts

Joined
Mon Jan 11, 2010 10:52 pm
Location - Austria

Post by OSWorX » Fri Aug 22, 2025 5:19 am

Lumirion wrote:
Thu Aug 21, 2025 3:40 am
The result is all public facing pages are blank white and no output is logged.
See last posting from me - white, blank pages are not really white and blank.

Full Stack Web Developer :: Dedicated OpenCart Development & Support DACH Region
Contact for Custom Work / Fast Support.


User avatar
Administrator

Posts

Joined
Mon Jan 11, 2010 10:52 pm
Location - Austria

Post by Lumirion » Fri Aug 22, 2025 5:56 am

@khnaz35 - After a couple hours this started showing up in the error log, "2025-08-21 16:08:17 - My controller is being called!".

New member
Online

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by Cue4cheap » Fri Aug 22, 2025 8:23 am

In addition to OSWorX you can create a php file in it with this: <?php phpinfo(); ?>
Whatever name you make it, lets say "sometheerrorlog.php" then you go to your website www.yourwebsite.com/sometheerrorlog.php
It should have a line with
Directive Local Value
error_log error_log

This will give you the error log name.

Please follow OSWorX info and this and get back to us. If you don't provide more info we are all going to just be guessing and shooting in the dark.
Mike

cue4cheap not cheap quality


Expert Member

Posts

Joined
Fri Sep 20, 2013 4:45 am

Post by OSWorX » Fri Aug 22, 2025 10:25 am

Lumirion wrote:
Fri Aug 22, 2025 5:56 am
@khnaz35 - After a couple hours this started showing up in the error log, "2025-08-21 16:08:17 - My controller is being called!".
After a couple hours ..
Means what?
A. you followed khnaz35 advice a few hours ago (which was at Thu Aug 21, 2025 3:13 pm ) and NOW this entry is logged (displayed).
B. you added this shortly and made also other changes as suggested and the entry is logged after all of that

Folks, why can you not be precise?
We here do not know when and what was made, we are not sitting beside you and see what you are doing!
And we all here have no crystal balls ..

Full Stack Web Developer :: Dedicated OpenCart Development & Support DACH Region
Contact for Custom Work / Fast Support.


User avatar
Administrator

Posts

Joined
Mon Jan 11, 2010 10:52 pm
Location - Austria

Post by OSWorX » Fri Aug 22, 2025 10:29 am

Cue4cheap wrote:
Fri Aug 22, 2025 8:23 am
In addition to OSWorX you can create a php file in it with this: <?php phpinfo(); ?>
Whatever name you make it, lets say "sometheerrorlog.php" then you go to your website www.yourwebsite.com/sometheerrorlog.php
Very good advice!

Just to repeat Mikes suggestion to rename that file or give him a "casual" name: scriptkiddies, bots and all those unwanted creatures are looking always for filenames having like phpinfo, admin, adminer, etc.

And to add: delete that file in any case after you do not need it anymore!

Full Stack Web Developer :: Dedicated OpenCart Development & Support DACH Region
Contact for Custom Work / Fast Support.


User avatar
Administrator

Posts

Joined
Mon Jan 11, 2010 10:52 pm
Location - Austria

Post by Lumirion » Fri Aug 22, 2025 11:58 pm

@OSWorX - Regarding further information.
1. Server admin tool – I don’t have access so I’m not sure what we use.
2. Is error_reporting enabled? Yes, via php.ini. Also, OpenCart settings says that “Display Errors” and “Log Errors” are both enabled.
3. Add snippet to index.php – Done.
You are correct about the blank page there is some html in there by default.
Also correct about the part that showed up in the log. I followed @khnaz35’s advice to put

Code: Select all

 $this->log->write('My controller is being called!'); 
in the index method. I moved around the site for a few minutes opening pages, then worked on another project for a bit and redownloaded the error log. There was no change. I worked on some other stuff for a bit and when I returned, I downloaded another fresh copy of the error log. It was around 2 hours later. Now the error log had changed. This was before any configuration changes. I just now added the change to the index.php file. I am about to try @Cue4cheap’s advice for locating the server log.
Additionally, I moved a copy of the getCategoryPath function to the catalog/model/catalog/category.php module, and called it from there. The function does complete from there and the pages are not blank anymore. I just haven’t been able to log the output yet.

New member
Online

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by OSWorX » Sat Aug 23, 2025 12:29 am

Lumirion wrote:
Fri Aug 22, 2025 11:58 pm
1. Server admin tool – I don’t have access so I’m not sure what we use.
That means, you're the webstore admin, but have no access to the server administration tool - correct?
Could you ask someone (store owner, server admin) to give you that information?

Because this is quite important for the future.
Why?
Last weeks had some clients who needed help with root servers, but having no clue what to do, which settings are good, which are bad (in case of security and speed)!
THE problem then is, we are dealing with sensitive data (customers, addresses, bank data, etc.) - if they are secured, we all (not I) on/in this webstore will have a problem (you know " .. houston we have a problem .. ")!

So better is to investigate a few bucks in a person who knows what he is doing - you and your customers will sleep better - believe me.

Full Stack Web Developer :: Dedicated OpenCart Development & Support DACH Region
Contact for Custom Work / Fast Support.


User avatar
Administrator

Posts

Joined
Mon Jan 11, 2010 10:52 pm
Location - Austria

Post by Cue4cheap » Sat Aug 23, 2025 12:49 am

Lumirion wrote:
Fri Aug 22, 2025 11:58 pm
Additionally, I moved a copy of the getCategoryPath function to the catalog/model/catalog/category.php module, and called it from there. The function does complete from there and the pages are not blank anymore. I just haven’t been able to log the output yet.
How about this... Please tell us and show us what you have and where.... Plus how you are calling it.

So far you have told us you move the function to the catalog/model/catalog/category.php module and called it from there. How?
Where di you place it in that file?

What command line or url are you using to call the function? What is passing the $category_id to the function?

What does your log line look like?

If you can show us all the code you are using and where/how you are using it a bunch of us could either duplicate what you are doing (and see if in our error_log file IF we get an error) or simply review your code and see if there is an issue with the code.

Mike

cue4cheap not cheap quality


Expert Member

Posts

Joined
Fri Sep 20, 2013 4:45 am

Post by Lumirion » Sat Aug 23, 2025 1:18 am

Here is the content of my ocmod file minus the header.

Code: Select all

  <file path="catalog/controller/journal3/catalog.php">
    <operation>
      <search><![CDATA[$data = parent::index($args);]]></search>
      <add position="after"><![CDATA[$this->log->write('My controller is being called!');]]></add>
    </operation>
    <operation>
      <search><![CDATA[public function index($args) {]]></search>
      <add position="before"><![CDATA[
	public function getCategoryPath($category_id) {
		if (!is_numeric($category_id) || $category_id <= 0) {
			return '';
		}

		$category_id = (int)$category_id;
		$path = [(string)$category_id];
		$seen_ids = [$category_id];

		while ($category_id > 0) {
			$query = $this->db->query("SELECT parent_id FROM " . DB_PREFIX . "category WHERE category_id = '" . $this->db->escape($category_id) . "'");
			if (!$query->num_rows) {
				break;
			}

			$parent_id = (int)$query->row['parent_id'];
			if (in_array($parent_id, $seen_ids)) {
				break;
			}

			if ($parent_id > 0) {
				$path[] = (string)$parent_id;
				$seen_ids[] = $parent_id;
				$category_id = $parent_id;
			} else {
				break;
			}
		}

		return implode('_', array_reverse($path));
	}
	  ]]></add>
    </operation>
	<operation>
      <search><![CDATA[foreach ($results as $result) {]]></search>
      <add position="after"><![CDATA[
							// $canonical_path = this->getCategoryPath($parser->getSetting('category'));
							$canonical_path = $this->model_catalog_category->getCategoryPath($parser->getSetting('category'));
							// $canonical_path = "Im working";
							$this->log = new \Log('PDP_Catalog.log');
							$this->log->write("The Canonical path for category id " . $category_info['name'] . " is " . $canonical_path);]]></add>
    </operation>
    <!--
	<operation>
      <search><![CDATA[$this->url->link('product/category', 'path=' . $category_path . '_' . $result['category_id']),]]></search>
      <add position="replace"><![CDATA[$this->url->link('product/category', 'path=' . $canonical_path . '_' . $result['category_id']),]]></add>
    </operation> -->
  </file>
  <file path="catalog/model/catalog/category.php">
  <operation>
      <search><![CDATA[public function getTotalCategories($parent_id) {]]></search>
      <add position="before"><![CDATA[
	public function getCategoryPath($category_id) {
		if (!is_numeric($category_id) || $category_id <= 0) {
			return '';
		}

		$category_id = (int)$category_id;
		$path = [(string)$category_id];
		$seen_ids = [$category_id];

		while ($category_id > 0) {
			$query = $this->db->query("SELECT parent_id FROM " . DB_PREFIX . "category WHERE category_id = '" . $this->db->escape($category_id) . "'");
			if (!$query->num_rows) {
				break;
			}

			$parent_id = (int)$query->row['parent_id'];
			if (in_array($parent_id, $seen_ids)) {
				break;
			}

			if ($parent_id > 0) {
				$path[] = (string)$parent_id;
				$seen_ids[] = $parent_id;
				$category_id = $parent_id;
			} else {
				break;
			}
		}
        $this->log->write("The Canonical path for category id " . $category_id . " is " . $path);
		return implode('_', array_reverse($path));
	}
	  ]]></add>
    </operation>
  </file>
And a clean copy of the catalog/controller/journal3/catalog.php

Code: Select all

<?php

use Journal3\Opencart\ModuleController;
use Journal3\Options\Parser;
use Journal3\Utils\Arr;

class ControllerJournal3Catalog extends ModuleController {

	public function __construct($registry) {
		parent::__construct($registry);
		$this->load->model('catalog/category');
		$this->load->model('catalog/manufacturer');
		$this->load->model('catalog/product');
		$this->load->model('journal3/category');
		$this->load->model('journal3/product');
	}

	public function index($args) {
		$data = parent::index($args);

		if (!$data) {
			return null;
		}

		if ($this->settings['carousel']) {
			$this->journal3->document->addStyle('catalog/view/theme/journal3/lib/swiper/swiper.min.css');
			$this->journal3->document->addScript('catalog/view/theme/journal3/lib/swiper/swiper.min.js', 'footer');
		}

		return $data;
	}

	/**
	 * @param Parser $parser
	 * @param $index
	 * @return array
	 */
	protected function parseGeneralSettings($parser, $index) {
		$data = array(
			'classes'         => array(
				'carousel-mode'  => $parser->getSetting('carousel'),
				'image-on-hover' => $parser->getSetting('changeImageOnHover'),
			),
			'carouselOptions' => $this->journal3->carousel($parser->getJs(), 'carouselStyle'),
		);

		if ($this->journal3->settings->get('performanceLazyLoadImagesStatus')) {
			$data['dummy_image'] = $this->model_journal3_image->transparent($parser->getSetting('imageDimensions.width'), $parser->getSetting('imageDimensions.height'));
		}

		return $data;
	}

	/**
	 * @param Parser $parser
	 * @param $index
	 * @return array
	 */
	protected function parseItemSettings($parser, $index) {
		$data = array(
			'classes' => array(
				'swiper-slide' => $this->settings['carousel'],
			),
			'items'   => array(),
			'image'   => '',
			'name'    => '',
			'href'    => '',
		);

		switch ($parser->getSetting('type')) {
			case 'category':
				$category_info = $this->model_catalog_category->getCategory($parser->getSetting('category'));

				if (!$category_info) {
					return null;
				}

				$category_path = (string)$parser->getSetting('category');

				if ($category_prefix = (string)Arr::get($this->module_args, 'category_prefix')) {
					$category_prefix_info = $this->model_catalog_category->getCategory($category_prefix);

					if ($category_prefix_info && ($category_path !== $category_prefix)) {
						$category_path = $category_prefix . '_' . $category_path;
					}
				}

				$data['href'] = $this->url->link('product/category', 'path=' . $category_path);
				$data['name'] = $category_info['name'];

				if ($this->settings['images']) {
					$data['image'] = $this->model_journal3_image->resize($category_info['image'], $this->settings['imageDimensions']['width'], $this->settings['imageDimensions']['height'], $this->settings['imageDimensions']['resize']);
					$data['image2x'] = $this->model_journal3_image->resize($category_info['image'], $this->settings['imageDimensions']['width'] * 2, $this->settings['imageDimensions']['height'] * 2, $this->settings['imageDimensions']['resize']);
				}

				switch ($parser->getSetting('subtype')) {
					case 'category':
						$data['total'] = $this->model_journal3_category->getTotalCategories($parser->getSetting('category'));

						$results = $this->model_journal3_category->getCategories($parser->getSetting('category'), $parser->getSetting('limit'));

						foreach ($results as $result) {
							$data['items'][] = array(
								'name'    => $result['name'],
								'href'    => $this->url->link('product/category', 'path=' . $category_path . '_' . $result['category_id']),
								'image'   => $this->settings['images'] ? $this->model_journal3_image->resize($result['image'], $this->settings['imageDimensions']['width'], $this->settings['imageDimensions']['height'], $this->settings['imageDimensions']['resize']) : '',
								'image2x' => $this->settings['images'] ? $this->model_journal3_image->resize($result['image'], $this->settings['imageDimensions']['width'] * 2, $this->settings['imageDimensions']['height'] * 2, $this->settings['imageDimensions']['resize']) : '',
							);
						}

						break;

					case 'product':
						$filter_data = array(
							'filter_category_id' => $parser->getSetting('category'),
							'limit'              => $parser->getSetting('limit'),
							'sort'               => 'p.sort_order',
						);

						$data['total'] = $this->model_journal3_product->getTotalProducts($filter_data);

						$results = $this->model_journal3_product->getProducts($filter_data);

						foreach ($results as $result) {
							$data['items'][] = array(
								'name'    => $result['name'],
								'href'    => $this->url->link('product/product', 'path=' . $category_path . '&product_id=' . $result['product_id']),
								'image'   => $this->settings['images'] ? $this->model_journal3_image->resize($result['image'], $this->settings['imageDimensions']['width'], $this->settings['imageDimensions']['height'], $this->settings['imageDimensions']['resize']) : '',
								'image2x' => $this->settings['images'] ? $this->model_journal3_image->resize($result['image'], $this->settings['imageDimensions']['width'] * 2, $this->settings['imageDimensions']['height'] * 2, $this->settings['imageDimensions']['resize']) : '',
							);
						}

						break;

					default:
						return null;
				}

				break;

			case 'manufacturer';
				$manufacturer_info = $this->model_catalog_manufacturer->getManufacturer($parser->getSetting('manufacturer'));

				if (!$manufacturer_info) {
					return null;
				}

				$data['href'] = $this->url->link('product/manufacturer/info', 'manufacturer_id=' . $parser->getSetting('manufacturer'));
				$data['name'] = $manufacturer_info['name'];

				if ($this->settings['images']) {
					$data['image'] = $this->model_journal3_image->resize($manufacturer_info['image'], $this->settings['imageDimensions']['width'], $this->settings['imageDimensions']['height'], $this->settings['imageDimensions']['resize']);
					$data['image2x'] = $this->model_journal3_image->resize($manufacturer_info['image'], $this->settings['imageDimensions']['width'] * 2, $this->settings['imageDimensions']['height'] * 2, $this->settings['imageDimensions']['resize']);
				}

				$filter_data = array(
					'filter_manufacturer_id' => $parser->getSetting('manufacturer'),
					'limit'                  => $parser->getSetting('limit'),
					'sort'                   => 'p.sort_order',
				);

				$data['total'] = $this->model_journal3_product->getTotalProducts($filter_data);

				$results = $this->model_journal3_product->getProducts($filter_data);

				foreach ($results as $result) {
					$data['items'][] = array(
						'name'    => $result['name'],
						'href'    => $this->url->link('product/product', 'manufacturer_id=' . $result['manufacturer_id'] . '&product_id=' . $result['product_id']),
						'image'   => $this->settings['images'] ? $this->model_journal3_image->resize($result['image'], $this->settings['imageDimensions']['width'], $this->settings['imageDimensions']['height'], $this->settings['imageDimensions']['resize']) : '',
						'image2x' => $this->settings['images'] ? $this->model_journal3_image->resize($result['image'], $this->settings['imageDimensions']['width'] * 2, $this->settings['imageDimensions']['height'] * 2, $this->settings['imageDimensions']['resize']) : '',
					);
				}

				break;

			default:
				return null;
		}

		return $data;
	}

	/**
	 * @param Parser $parser
	 * @param $index
	 * @return array
	 */
	protected function parseSubitemSettings($parser, $index) {
		return array();
	}

}

New member
Online

Posts

Joined
Fri Apr 19, 2024 1:32 am

Post by khnaz35 » Sat Aug 23, 2025 2:53 am

How about giving it short with this version and look at the logs after refresh the modifications

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<modification>
  <name>Journal3 Catalog Logging + Category Canonical Path</name>
  <code>j3_catalog_logging_category_path</code>
  <version>1.0</version>
  <author><![CDATA[<font color="#19700E"><b>khnaz35</b></font>]]></author>
  <link>mailto:khnaz35@gmail.com</link>

  <!-- =========================
       CONTROLLER: journal3/catalog.php
       ========================= -->
  <file path="catalog/controller/journal3/catalog.php">

    <!-- Log immediately when index() is entered -->
    <operation>
      <search><![CDATA[public function index($args) {]]></search>
      <add position="after"><![CDATA[
        if (isset($this->log)) {
          $this->log->write('[Journal3\\Catalog::index] Entered with args: ' . (is_scalar($args) ? (string)$args : json_encode($args)));
        }
      ]]></add>
    </operation>

    <!-- Log right after parent::index($args) returns -->
    <operation>
      <search><![CDATA[$data = parent::index($args);]]></search>
      <add position="after"><![CDATA[
        if (isset($this->log)) {
          $this->log->write('[Journal3\\Catalog::index] parent::index completed.');
        }
      ]]></add>
    </operation>

    <!-- When looping results, compute and log canonical path safely -->
    <operation>
      <search><![CDATA[foreach ($results as $result) {]]></search>
      <add position="after"><![CDATA[
        if (isset($this->log)) {
          $this->log->write('[Journal3\\Catalog::index] Iterating result. category_id: ' . (isset($result['category_id']) ? (int)$result['category_id'] : 'n/a'));
        }

        $canonical_path = '';
        try {
          // Journal3 typically exposes $parser; guard for safety.
          if (isset($parser) && is_object($parser) && method_exists($parser, 'getSetting')) {
            $category_setting = $parser->getSetting('category');
            if (isset($this->log)) {
              $this->log->write('[Journal3\\Catalog::index] parser->getSetting("category") => ' . (is_scalar($category_setting) ? (string)$category_setting : json_encode($category_setting)));
            }

            if (!empty($category_setting) && is_numeric($category_setting)) {
              if (isset($this->load)) {
                $this->load->model('catalog/category');
              }
              if (isset($this->model_catalog_category) && method_exists($this->model_catalog_category, 'getCategoryPath')) {
                $canonical_path = $this->model_catalog_category->getCategoryPath((int)$category_setting);
              }
            }
          } else {
            if (isset($this->log)) {
              $this->log->write('[Journal3\\Catalog::index] $parser missing or getSetting not available.');
            }
          }
        } catch (\Exception $e) {
          if (isset($this->log)) {
            $this->log->write('[Journal3\\Catalog::index] Exception while computing canonical path: ' . $e->getMessage());
          }
        }

        if (isset($this->log)) {
          $logged_name = isset($category_info['name']) ? $category_info['name'] : 'unknown';
          $this->log->write('[Journal3\\Catalog::index] Canonical path for category "' . $logged_name . '" = ' . (string)$canonical_path);
        }
      ]]></add>
    </operation>

    <!-- Optional: If you later want to switch links to use $canonical_path, uncomment your replace op.
    <operation>
      <search><![CDATA[$this->url->link('product/category', 'path=' . $category_path . '_' . $result['category_id']),]]></search>
      <add position="replace"><![CDATA[$this->url->link('product/category', 'path=' . $canonical_path . '_' . $result['category_id']),]]></add>
    </operation>
    -->
  </file>

  <!-- =========================
       MODEL: catalog/model/catalog/category.php
       ========================= -->
  <file path="catalog/model/catalog/category.php">
    <!-- Inject getCategoryPath() with comprehensive logging -->
    <operation>
      <search><![CDATA[public function getTotalCategories($parent_id) {]]></search>
      <add position="before"><![CDATA[
        /**
         * Build full "path" for a category by walking up the tree to root.
         * Logs lifecycle, guards cycles, and returns a string like "12_3_1".
         */
        public function getCategoryPath($category_id) {
          if (!is_numeric($category_id) || (int)$category_id <= 0) {
            if (isset($this->log)) {
              $this->log->write('[Model\\Catalog\\Category::getCategoryPath] Invalid category_id: ' . print_r($category_id, true));
            }
            return '';
          }

          $category_id = (int)$category_id;
          $path = [$category_id];
          $seen_ids = [$category_id];

          if (isset($this->log)) {
            $this->log->write('[Model\\Catalog\\Category::getCategoryPath] Start. category_id=' . $category_id);
          }

          while ($category_id > 0) {
            $query = $this->db->query("SELECT parent_id FROM " . DB_PREFIX . "category WHERE category_id = '" . (int)$category_id . "'");

            if (!$query->num_rows) {
              if (isset($this->log)) {
                $this->log->write('[Model\\Catalog\\Category::getCategoryPath] No DB row for category_id=' . $category_id . '; stopping.');
              }
              break;
            }

            $parent_id = (int)$query->row['parent_id'];

            if (in_array($parent_id, $seen_ids, true)) {
              if (isset($this->log)) {
                $this->log->write('[Model\\Catalog\\Category::getCategoryPath] Detected cycle at parent_id=' . $parent_id . '; current path=' . implode('_', array_reverse(array_map('strval', $path))));
              }
              break;
            }

            if ($parent_id > 0) {
              $path[] = $parent_id;
              $seen_ids[] = $parent_id;
              if (isset($this->log)) {
                $this->log->write('[Model\\Catalog\\Category::getCategoryPath] Ascend to parent_id=' . $parent_id);
              }
              $category_id = $parent_id;
            } else {
              if (isset($this->log)) {
                $this->log->write('[Model\\Catalog\\Category::getCategoryPath] Reached root (parent_id=0).');
              }
              break;
            }
          }

          $final_path = implode('_', array_reverse(array_map('strval', $path)));

          if (isset($this->log)) {
            $this->log->write('[Model\\Catalog\\Category::getCategoryPath] Final path=' . $final_path);
          }

          return $final_path;
        }
      ]]></add>
    </operation>
  </file>
</modification>

Got a burning question at 3 AM that even Google shrugs at? There’s a not-so-secret inbox that might just have your answer: khnaz35@gmail.com
Breathe in some nature while you're at it. It’s cheaper than therapy. :-*

Feel free to sling a bear my way via PayPal @ khnaz35@gmail.com


User avatar
Active Member
Online

Posts

Joined
Mon Aug 27, 2018 11:30 pm
Location - Malaysia

Post by Lumirion » Sat Aug 23, 2025 5:05 am

I disabled my ocmod and added yours. I cleared caches, went through a few pages as a test. They loaded fine. I downloaded a new copy of the error log, but so far it's just repeating the same warnings and logs from my other unrelated mods.

New member
Online

Posts

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

Users browsing this forum: Lumirion and 17 guests