Smart Search

  • Posts: 426
  • Thank you received: 19
4 months 1 week ago #361946

-- HikaShop version -- : 5.1.0
-- Joomla version -- : 5.1.1

Hi, I noticed two bugs in the Smart Search after indexing.
1. Products are not displayed in types in the Smart Search: Content Maps section


2. Products are not displayed in Smart Search: Search Filters section when creating a new filter

Attachments:
Last edit: 4 months 1 week ago by neo191987.

Please Log in or Create an account to join the conversation.

  • Posts: 82823
  • Thank you received: 13370
  • MODERATOR
4 months 1 week ago #361947

Hi,

I've looked into it for a few hours but I couldn't find why that is the case. I compared what is done in our smart search plugin and other plugins and I don't see what could explain this.
I've posted the question groups.google.com/g/joomla-dev-general
Hopefully, someone more knowledgeable on this can help.

The following user(s) said Thank You: neo191987

Please Log in or Create an account to join the conversation.

  • Posts: 426
  • Thank you received: 19
4 months 1 week ago #361952

I will try to write a plugin and if everything works as it should I will share it.

The following user(s) said Thank You: Philip

Please Log in or Create an account to join the conversation.

  • Posts: 426
  • Thank you received: 19
4 months 1 week ago #361986

I made a test plugin and it works properly. Can you create a plugin based on this?

<?php
/**
 * @package	HikaShop for Joomla!
 * @version	5.1.0
 * @author	hikashop.com
 * @copyright	(C) 2010-2024 HIKARI SOFTWARE. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Version;

$version=new Version();
$JoomlaVersion=$version->getShortVersion();
if(version_compare($JoomlaVersion,'4.0.0','>=')){
	JLoader::registerAlias('FinderIndexerAdapter','Joomla\Component\Finder\Administrator\Indexer\Adapter');
	JLoader::registerAlias('FinderIndexerResult','Joomla\Component\Finder\Administrator\Indexer\Result');
}
else{
	JLoader::register('FinderIndexerAdapter',JPATH_ADMINISTRATOR.'/components/com_finder/helpers/indexer/adapter.php');
	JLoader::register('FinderIndexerResult',JPATH_ADMINISTRATOR.'/components/com_finder/helpers/indexer/result.php');
}

class plgFinderHikashop extends FinderIndexerAdapter{
	
	protected $context='Hikashop';
	protected $extension='com_hikashop';
	protected $layout='product';
	protected $type_title='Product';
	protected $table='#__hikashop_product';
	protected $state_field='product_published';
	protected $autoloadLanguage=true;
	
	public function onFinderAfterDelete($context,$table){
		if($context==='com_hikashop.product'){
			$id=$table->product_id;
		}
		elseif($context==='com_finder.index'){
			$id=$table->link_id;
		}
		else{
			return true;
		}
		return $this->remove($id);
	}
	
	public function onFinderAfterSave($context,$row,$isNew){
		if($context==='com_hikashop.product'){
			if(!$isNew&&$this->old_access!=$row->access){
				$this->itemAccessChange($row);
			}
			$this->reindex($row->product_id);
		}
		return true;
	}
	
	public function onFinderBeforeSave($context,$row,$isNew){
		if($context==='com_hikashop.product'){
			if(!$isNew){
				$this->checkItemAccess($row);
			}
		}
		return true;
	}
	
	public function onFinderChangeState($context,$pks,$value){
		if($context==='com_hikashop.product'){
			$this->itemStateChange($pks,$value);
		}
		if($context==='com_plugins.plugin'&&$value===0){
			$this->pluginDisable($pks);
		}
	}
	
	protected function index(FinderIndexerResult $item,$format='html'){
		$item->setLanguage();
		if(ComponentHelper::isEnabled($this->extension)===false){
			return;
		}
		$item->context='com_hikashop.product';
		$item->url=$this->getUrl($item->product_id,$this->extension,$this->layout);
		$item->route='';
		$item->title=$item->product_name;
		$item->summary=$item->product_description;
		$item->body=$item->product_description;
		$item->addTaxonomy('Type','Product');
		$item->addTaxonomy('Language',$item->language);
		$this->indexer->index($item);
	}
	
	protected function setup(){
		require_once JPATH_ADMINISTRATOR.'/components/com_hikashop/helpers/helper.php';
		return true;
	}
	
	protected function getListQuery($query=null){
		$db=Factory::getDbo();
		$query=$query instanceof JDatabaseQuery?$query:$db->getQuery(true)->select('p.product_id, p.product_name, p.product_description')->from('#__hikashop_product AS p');
		return $query;
	}
	
}

Please Log in or Create an account to join the conversation.

  • Posts: 82823
  • Thank you received: 13370
  • MODERATOR
4 months 1 week ago #362017

Hi,

Thanks for your feedback on this.
Actually what you do is basically a simplified version of what we do in the plugin, without all the extra bells and whistles to handle different things.
One such thing is the multilingual indexing.
And thinking about this while writing this message made me think: what if the problem was actually because we make a copy of the item to be indexed for each language so that we can index the products in different languages ? Maybe the taxonomy is lost during the copy process ?

And so, I've added the line:

$copy->addTaxonomy('Type', 'Product');
after the line:
$copy->language = $language->code;
in the file hikashop.php of the finder plugin of HikaShop. Then, I deleted the index, reindexed everything, and now I have the product type properly set in the content map. So I finally found what was the problem.
I'll be adding the patch for this on our end.

The following user(s) said Thank You: neo191987

Please Log in or Create an account to join the conversation.

  • Posts: 426
  • Thank you received: 19
4 months 2 days ago #362203

Hi, I went back to Joomla 4 and again a problem appeared. Products are not selectable in the Smart Search: New Filter section and after indexing in the Smart Search: Content Maps section are unpublished by default.

Please Log in or Create an account to join the conversation.

  • Posts: 426
  • Thank you received: 19
4 months 2 days ago #362209

I found that the problem again comes from handleOtherLanguages

Please Log in or Create an account to join the conversation.

  • Posts: 82823
  • Thank you received: 13370
  • MODERATOR
4 months 1 day ago #362205

Hi,

What do you mean by "I went back to Joomla 4" ? It is the same website ? Another website ? Did you apply the patch in the hikashop.php file as I mentioned in my previous message ? Did you clear the index and reindex everything after adding the patch ?

Last edit: 4 months 2 days ago by nicolas.

Please Log in or Create an account to join the conversation.

  • Posts: 426
  • Thank you received: 19
4 months 1 day ago #362216

Unfortunately I applied the patch but it doesn't work for Joomla 4, for Joomla 5 it works fine. I had switched to Joomla 5 for a compatibility test but had problems with several components and was forced to revert to version 4. I really can't figure out exactly why it works fine in 5 but crashes again in 4. Try the same test as with Joomla 5, but with version 4 (last version).

Last edit: 4 months 1 day ago by neo191987.

Please Log in or Create an account to join the conversation.

  • Posts: 426
  • Thank you received: 19
4 months 1 day ago #362219

These are the results for me with the latest version of Joomla 4 and Hikashop

Attachments:

Please Log in or Create an account to join the conversation.

  • Posts: 426
  • Thank you received: 19
4 months 1 day ago #362220

If I change the code of the file hikashop_j4.php line 160-162 from

if(!$this->handleOtherLanguages($item)) {
$this->indexer->index($item);
}

to be
$this->indexer->index($item);

The result will be the following



Now it works normally.

Attachments:
The following user(s) said Thank You: nicolas

Please Log in or Create an account to join the conversation.

  • Posts: 426
  • Thank you received: 19
3 months 4 weeks ago #362266

Hi, I solved the problem with indexing the multilingual products. I post the code if you like it you can use it.

In the handleOtherLanguages(&$item) function, instead of true or false, I added under different conditions what to execute

protected function handleOtherLanguages(&$item) {
    $translationHelper = hikashop_get('helper.translation');
    if ($translationHelper->isMulti()) {
      $languages = $translationHelper->loadLanguages();
      $mainColumns = array('title' => 'product_name', 'summary' => 'product_description', 'metakey' => 'product_keywords', 'metadesc' => 'product_meta_description', 'product_alias' => 'product_alias');
      $fields = $this->params->get('fields');
      if (!is_array($fields)) {
        $fields = explode(',', (string)$fields);
      }
      if (!empty($fields) && count($fields)) {
        $columns = array_merge($mainColumns, $fields);
      }
      else {
        $columns = $mainColumns;
      }
      foreach ($languages as $language) {
        if (method_exists($item, 'serialize')) {
          $serialize = $item->serialize();
          $class = $this->resultClass;
          $copy = new $class();
          @$copy->unserialize($serialize);
        }
        else {
          $copy = hikashop_copy($item);
        }
        $copy->language = $language->code;
        $copy->addTaxonomy('Language', $copy->language);
        $copy->addTaxonomy('Type', 'Product');
        if ($translationHelper->falang) {
          $db = JFactory::getDBO();
          $dbColumns = array();
          foreach ($columns as $column) {
            $dbColumns[] = $db->Quote($column);
          }
          $query = 'SELECT * FROM #__falang_content WHERE published=1 AND language_id = ' . (int)$language->id . ' AND reference_table=\'hikashop_product\' AND reference_id = ' . (int)$item->id . ' AND reference_field IN (' . implode(',', $dbColumns) . ')';
          $db->setQuery($query);
          $translations = $db->loadObjectList();
          if (!empty($translations)) {
            foreach ($translations as $t) {
              if (empty($t->value)) continue;
              $column = $t->reference_field;
              $copy->$column = $t->value;
              if (in_array($column, $mainColumns)) {
                $key = array_search($column, $mainColumns);
                if ($key == 'summary') {
                  $copy->summary = $this->prepareContent($copy->$column, $copy->params);
                }
                else {
                  $copy->$key = $copy->$column;
                }
              }
            }
          }
        }
        else {
          $originals = array();
          foreach ($columns as $column) {
            if (!empty($item->$column)) {
              $originals[$column] = $item->$column;
            }
          }
          if (count($originals)) {
            $translations = hikashop_translate($originals, $language->code);
            foreach ($originals as $k => $o) {
              if ($o == $translations[$k]) continue;
              $copy->$k = $translations[$k];
              foreach ($columns as $column) {
                if (in_array($column, $mainColumns)) {
                  $key = array_search($column, $mainColumns);
                  if ($key == 'summary') {
                    $copy->summary = $this->prepareContent($copy->$column, $copy->params);
                  }
                  else {
                    $copy->$key = $copy->$column;
                  }
                }
              }
            }
          }
        }
        $copy->alias = '';
        $this->addAlias($copy);
        $extra = $this->_getElementMenuItem($copy);
        $SEFlanguages = JLanguageHelper::getLanguages('sef');
        foreach ($SEFlanguages as $sef => $lang) {
          if ($lang->lang_code == $language->code) {
            $extra .= '&lang=' . $sef;
            break;
          }
        }
        $copy->url = "index.php?option=com_hikashop&ctrl=product&task=show&cid=" . $copy->id . "&name=" . $copy->alias . $extra;
        $copy->route = "index.php?option=com_hikashop&ctrl=product&task=show&cid=" . $copy->id . "&name=" . $copy->alias . $extra;
        $this->indexer->index($copy);
      }
    }
    else {
      return;
    }
  }

Instead
if(!$this->handleOtherLanguages($item)) {
$this->indexer->index($item);
}

I changed it to
$this->indexer->index($item);
$this->handleOtherLanguages($item);

Now it works properly, test it and give your opinion.

After a long analysis, I realized that this bug occurs when there is no language - All. This language is the default and must be included when indexing.

Last edit: 3 months 4 weeks ago by neo191987.

Please Log in or Create an account to join the conversation.

  • Posts: 426
  • Thank you received: 19
3 months 4 weeks ago #362272

I tested all kinds of options and this is the best result without any bugs.

In hikashop.php, you forgot to add

protected $autoloadLanguage = true;

I changed the protected function handleOtherLanguages(&$item) and added an additional function to clean language - all, so it doesn't bug anymore. The code looks like this.
protected function handleOtherLanguages(&$item) {
    $translationHelper = hikashop_get('helper.translation');
    if ($translationHelper->isMulti()) {
      $languages = $translationHelper->loadLanguages();
      $mainColumns = array('title' => 'product_name', 'summary' => 'product_description', 'metakey' => 'product_keywords', 'metadesc' => 'product_meta_description', 'product_alias' => 'product_alias');
      $fields = $this->params->get('fields');
      if (!is_array($fields)) {
        $fields = explode(',', (string)$fields);
      }
      if (!empty($fields) && count($fields)) {
        $columns = array_merge($mainColumns, $fields);
      }
      else {
        $columns = $mainColumns;
      }
      foreach ($languages as $language) {
        if (method_exists($item, 'serialize')) {
          $serialize = $item->serialize();
          $class = $this->resultClass;
          $copy = new $class();
          @$copy->unserialize($serialize);
        }
        else {
          $copy = hikashop_copy($item);
        }
        $copy->language = $language->code;
        $copy->addTaxonomy('Language', $copy->language);
        $copy->addTaxonomy('Type', 'Product');
        if ($translationHelper->falang) {
          $db = JFactory::getDBO();
          $dbColumns = array();
          foreach ($columns as $column) {
            $dbColumns[] = $db->Quote($column);
          }
          $query = 'SELECT * FROM #__falang_content WHERE published=1 AND language_id = ' . (int)$language->id . ' AND reference_table=\'hikashop_product\' AND reference_id = ' . (int)$item->id . ' AND reference_field IN (' . implode(',', $dbColumns) . ')';
          $db->setQuery($query);
          $translations = $db->loadObjectList();
          if (!empty($translations)) {
            foreach ($translations as $t) {
              if (empty($t->value)) continue;
              $column = $t->reference_field;
              $copy->$column = $t->value;
              if (in_array($column, $mainColumns)) {
                $key = array_search($column, $mainColumns);
                if ($key == 'summary') {
                  $copy->summary = $this->prepareContent($copy->$column, $copy->params);
                }
                else {
                  $copy->$key = $copy->$column;
                }
              }
            }
          }
        }
        else {
          $originals = array();
          foreach ($columns as $column) {
            if (!empty($item->$column)) {
              $originals[$column] = $item->$column;
            }
          }
          if (count($originals)) {
            $translations = hikashop_translate($originals, $language->code);
            foreach ($originals as $k => $o) {
              if ($o == $translations[$k]) continue;
              $copy->$k = $translations[$k];
              foreach ($columns as $column) {
                if (in_array($column, $mainColumns)) {
                  $key = array_search($column, $mainColumns);
                  if ($key == 'summary') {
                    $copy->summary = $this->prepareContent($copy->$column, $copy->params);
                  }
                  else {
                    $copy->$key = $copy->$column;
                  }
                }
              }
            }
          }
        }
        $copy->alias = '';
        $this->addAlias($copy);
        $extra = $this->_getElementMenuItem($copy);
        $SEFlanguages = JLanguageHelper::getLanguages('sef');
        foreach ($SEFlanguages as $sef => $lang) {
          if ($lang->lang_code == $language->code) {
            $extra .= '&lang=' . $sef;
            break;
          }
        }
        $copy->url = "index.php?option=com_hikashop&ctrl=product&task=show&cid=" . $copy->id . "&name=" . $copy->alias . $extra;
        $copy->route = "index.php?option=com_hikashop&ctrl=product&task=show&cid=" . $copy->id . "&name=" . $copy->alias . $extra;
        $this->indexer->index($copy);
        $this->clearAllLanguage($item);
      }
    }
    else {
      return;
    }
  }
  
  protected function clearAllLanguage(&$item) {
    $db = JFactory::getDBO();
    $query = $db->getQuery(true);
    $conditions = array($db->quoteName('language') . ' = ' . $db->quote('*'), $db->quoteName('type_id') . ' = ' . $item->type_id);
    $query->delete($db->quoteName('#__finder_links'));
    $query->where($conditions);
    $db->setQuery($query);
    $db->execute();
  }

In the file hikashop j4.php in the protected function index(Joomla\Component\Finder\Administrator\Indexer\Result $item) at the top should be added
$item->setLanguage();

At the bottom, the code will remain
$this->indexer->index($item);
$this->handleOtherLanguages($item);

this is the end result

Attachments:
Last edit: 3 months 4 weeks ago by neo191987.

Please Log in or Create an account to join the conversation.

Time to create page: 0.123 seconds
Powered by Kunena Forum