XF 2.1 Custom addon data is not importing

CMTV

Well-known member
I have a simple ParamDefinition entity which is almost the same as WidgetDefinition entity.

ParamDefinition has an addon_id column so I need to export, import param definitions just as widget definitions.

What I have done:
  • Added XF:DevOutputWritable behaviour with all necessary checkings in _postDelete() and _postSave()
  • Created DevelopmentOutput\ParamDefinition class so now it successfully creates json files in _output folder
  • Created AddOn\DataType\ParamDefinition class which basically is almost a copy of WidgetDefinition data type class
  • Extended DataManager's getDataTypeClasses method so it contains the short name of my ParamDefinition entity
Now, XenForo successfully writes my ParamDefinition entities to _data/param_definitions.xml file:
XML:
<?xml version="1.0" encoding="utf-8"?>
<param_definitions>
  <param_definition definition_id="text_box" definition_class="\CMTV\CriteriaBuilder\Param\TextBox" icon="fa-font"/>
</param_definitions>

The problem is that these params are not importing when installing my addon on test forum.

What am I doing wrong? Do I need to perform additional steps when installing/upgrading addon? I am really new to this part of XenForo addon development...
 
Last edited:
My suspicion would be that your extensions to the data manager et al. aren't available until after the add-on is installed. If that's the case, I'm not sure if there's a way around it beyond abstracting these pieces into a separate add-on and having this add-on depend on it via addon.json.
 
Well this is strange since enqueueImportAddOnData($addOn) is called after installation (Admin\Controller\AddOn.php):
PHP:
public function actionInstall(ParameterBag $params)
{
   $addOn = $this->assertAddOnAvailable($params->addon_id_url);
   if (!$addOn->canInstall())
   {
      return $this->error(\XF::phrase('this_add_on_cannot_be_installed'));
   }

   list ($warnings, $errors) = $this->getAddOnWarningsAndErrors($addOn);

   if ($this->isPost())
   {
      // this applies to add-on changes as well, so we want to ensure errors here are shown and logged
      \XF::app()->error()->setIgnorePendingUpgrade(true);

      $input = $this->filter([
         '_xfProcessing' => 'bool',
         'params' => 'json-array',
         'count' => 'uint',
         'finished' => 'bool'
      ]);

      if ($input['finished']) /* ========= I SUPPOSE "DataManager" IS EXTENDED ALREADY? ========= */
      {
         $dataManager = $this->app->addOnDataManager();
         $dataManager->enqueueImportAddOnData($addOn); /* ========= THIS DOES NOT SEEM TO BE CALLED FOR MY ADDON ========= */

         return $this->redirect($this->getFinalizeUrl($addOn, 'install'));
      }
 
Last edited:
abstracting these pieces into a separate add-on and having this add-on depend on it via addon.json.
Ohh, now this is going to be messy. I thought XenForo supports a better way of creating addon-related entities that support importing/exporting. :unsure:
 
Well this is strange since enqueueImportAddOnData($addOn) is called after installation (Admin\Controller\AddOn.php):
I could be wrong as I haven't dug into the internals of add-on installation much, but as far as I'm aware class extensions and the like are part of the enqueueImportAddOnData() process (as they are exported to XML and must be imported like the templates, phrases, and the like).

Ohh, now this is going to be messy. I thought XenForo supports a better way of creating addon-related entities that support importing/exporting. :unsure:
Yeah, there might be a better way since it does seem the system was designed to allow for custom add-on data types. I'm not familiar enough with it to know one way or the other.
 
as far as I'm aware class extensions and the like are part of the enqueueImportAddOnData() process
Yeah, did not think about that...

This is not working too (Setup.php):
PHP:
public function postInstall(array &$stateChanges)
{
    \XF::app()->jobManager()->enqueueUnique('test_import_id', 'XF:AddOnData', [
        'addon_id' => C::ADDON_ID
    ]);
}

WAIT! It actually seems to work! Let me check again.
 
Yes. Importing addon data in postInstall() works perfectly:
I think you want to look using at the postInstall and postUpgrade methods in your add-on setup class. When those run, you're generally guaranteed to have your add-on be active again.


The only questions left:
  • Why do we need XF:DevOutputWritable behaviour and _output folder if addon data is kept in _data folder?
  • Is it okay to extend DataManager's getDataTypeClasses() method? If so, why there is no code event to do this via ACP?
  • How do I update imported entities with new version of addon?
 
One thing to consider is, by default, XF will set is_processing to true for the add-on before importing the data and set it back to false afterwards. This causes class extensions, code event listeners, and routes for the add-on to be disabled. By enqueuing the job directly you side-step this process, which may have unintended consequences. Of course without side-stepping this process, it wouldn't work (as before, the class extensions wouldn't be active to import your custom data type).

Why do we need XF:DevOutputWritable behaviour and _output folder if addon data is kept in _data folder?
_output is just for development purposes, while _data is for distributing the add-on to others (or for production). The documentation elaborates a little bit. I don't commit the _data directory to git repositories, for example.

How do I update imported entities with new version of addon?
Generally you import and export development and production data using the CLI tool:

Be careful as exporting without importing first can overwrite any local data that was not yet imported (ie if you had changed a template and not yet imported it).
 
Top Bottom