Tags autocomplete on Prestashop product edit page

As by now, Prestashop (1.5.6.1) has no tags autocomplete in admin panel on product edit page. This feature may be very handy especially when you have many tags and do not want to duplicate their meanings.

For PrestaShop 1.5.x

If this method doesn’t work for you then try next method for older Prestashop 1.5.x versions.

There are only 3 files that should be edited for that:

Create (or add) file override/classes/Tag.php with following contents:

<?php
class Product extends ProductCore
{
  public static function getTags($id_lang, $nb = 10) {
    return Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
      SELECT t.`name`
      FROM `'._DB_PREFIX_.'tag` t
      WHERE t.`id_lang` = '.(int)$id_lang.'
      ORDER BY t.`name` ASC
      LIMIT 0, '.(int)$nb);
  }
}

Then create file override/classes/Product.php with following contents:

<?php
class Tag extends TagCore
{
  public function getAllTags($id_lang = 0, $qty = 10){
    if(!$id_lang){
      $context = Context::getContext();
      $id_lang = $context->language->id;
    }

    return Tag::getTags($id_lang, $qty);
  }
}

If you created any of these 2 files then you’ll have to remove file cache/class_index.php as otherwise these functions will not be accessible until you’ll do that.

We’ll access this function directly from template (which is wrong following MVC idea). A better way to do this is to assign tags values to smarty from ProductController. But this is for those passioned of rules.

The last thing that we have to add is

{literal}
<script type="text/javascript">
  $().ready(function () {
    var id_lang = '{/literal}{$language.id_lang}{literal}'
      , availableTags = []
      , $input = $('#tags_' + id_lang)

    {/literal}
    {foreach from=$product->getAllTags($language.id_lang) item=tag}
      availableTags.push("{$tag.name}")
    {/foreach}
    {literal}

    $input
      .tagify({
        delimiters: [13,44]
      , addTagPrompt: '{/literal}{l s='Add tag' js=1}{literal}'
      })
    $input.tagify('inputField')
      .autocomplete(availableTags, {
        matchContains: true
      })
      .result(function(event, data, formatted) {
        var values = $input.tagify('serialize').replace(', ', ',').split(',')
        if (data.length && !~values.indexOf(data[0])) {
          $input.tagify('add', data[0])
        } else {
          $input.tagify('inputField').val('')
        }
      })

    $({/literal}'#{$table}{literal}_form').submit( function() {
      $(this).find('#tags_' + id_lang).val($input.tagify('serialize'));
    });
  });
</script>
{/literal}

It should replace last literal tags’ contents in file admin/themes/default/template/controllers/products/informations.tpl. These are lines 378 to 388 for me.

But you should take care about last change as we did it in default template, so anytime you’ll update your Prestashop, this file may be overridden. One way to deal with this case is to create a custom admin template, so nothing will bother you. But in case that if you’ll want latest admin template updates - you’ll have to merge differences, which may take a lot of time.

For PrestaShop 1.5.2 and lower

There are only 3 or 4 (depends on version) files that should be edited for that:

classes/Tag.php - apply this patch in case you are on stable version 1.5.2.0 or lower.

Add  override/classes/Tag.php and override/classes/Product.php as in previous method.

The last thing that we have to add is

<script type="text/javascript">
  $(function(){
    {foreach from=$languages item=language}
      var availableTags_{$language.id_lang} = []
      {foreach from=$product->getAllTags($language.id_lang) item=tag}
        availableTags_{$language.id_lang}.push("{$tag.name}")
      {/foreach}

      $('#tags_{$language.id_lang}').autocomplete(availableTags_{$language.id_lang}, {
        multiple: true
      , matchContains: true
      })
    {/foreach}
  })
</script>

It should be aded into admin/themes/default/template/controllers/products/informations.tpl right after previous script declaration. It is line 83 for me.

But you should take care about last change as we did it in default template, so anytime you’ll update your Prestashop, this file may be overridden. One way to deal with this case is to create a custom admin template, so nothing will bother you. But in case that if you’ll want latest admin template updates - you’ll have to merge differences, which may take a lot of time.

For PrestaShop 1.4.x

For version 1.4.x (tested on 1.4.9) of PrestaShop we have to change 2 files:

patch classes/Tag.php around line 99

$tmpTab = array_filter(array_unique(array_map('trim', preg_split('/,/', $string, NULL, PREG_SPLIT_NO_EMPTY))));

also add in this file to TagCore class following function:

public static function getTags($id_lang, $nb = 10) {
  return Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
    SELECT t.`name`
    FROM `'._DB_PREFIX_.'tag` t
    WHERE t.`id_lang` = '.(int)$id_lang.'
    ORDER BY t.`name` ASC
    LIMIT 0, '.(int)$nb);
}

admin/tabs/AdminProducts.php

$tags_lang = Tag::getTags($language['id_lang'], 999);
$tags_array = array();
foreach($tags_lang as $tag){
  $tags_array[] = $tag['name'];
}
echo '<script type="text/javascript">
      $(function(){
        $("#tags_'.$language['id_lang'].'").autocomplete(["'.implode('","', $tags_array).'"], {
          multiple: true
        , matchContains: true
        })
      })
      </script>';

It should be added on line 2915 in tags foreach loop. On first row you can see a magic 999 number - it is max number of tags that will be preloaded for each language.