Admin Template "<xen:option ..." in TemplateHook

r1pe

Member
Hello,

I have a question regarding the template function "<xen: option ... " in the "forum_edit" admin template file. I want to extend the "Forum Options" tab. XenForo use the template function "<xen: option ..." to build an option field in this template.

Code:
                <xen:option name="allow_posting" label="{xen:phrase allow_new_messages_to_be_posted_in_this_forum}" selected="{$forum.allow_posting}">
                    <xen:hint>{xen:phrase if_disabled_users_not_able_post_messages_in_forum}</xen:hint>
                </xen:option>

How can I build an option field in a TemplateHook file? Sure, I could use normal HTML but I think there is a better solution.

Thanks in advance.
 
If you echo out the template hook the existing contents will actually be normal HTML.

At that point the template has been compiled so it will be too late to use xen tags.

However from your template hook you can inject a new template using $template->create() that new template can contain xen tags.
 
Here is an example from my site:

Create your additional forum options template:
Code:
    <xen:spinboxunit name="xp_mod" value="{$xpModOptions.xp_mod}" step="1" min="0" max="100" label="{xen:phrase iwd_experience_modifier}:">
        <xen:explain>{xen:phrase iwd_experience_modifier_explain}</xen:explain>
    </xen:spinboxunit>
    <xen:spinboxunit name="gold_mod" value="{$xpModOptions.gold_mod}" step="1" min="0" max="100" label="{xen:phrase iwd_gold_percentage}:">
        <xen:explain>{xen:phrase iwd_gold_percentage_explain}</xen:explain>
    </xen:spinboxunit>
    <xen:checkboxunit label="{xen:phrase iwd_iwd_options}:">
        <xen:option name="encounter" label="{xen:phrase iwd_enable_encounters}" selected="{$xpModOptions.encounter}">
            <xen:hint>{xen:phrase iwd_if_disabled_random_encounters_will_be_turned_off}</xen:hint>
        </xen:option>
        <xen:option name="trap" label="{xen:phrase iwd_enable_traps}" selected="{$xpModOptions.trap}">
            <xen:hint>{xen:phrase iwd_if_enabled_random_traps_will_be_turned_on}</xen:hint>
        </xen:option>
        <xen:option name="treasure" label="{xen:phrase iwd_enable_treasure}" selected="{$xpModOptions.treasure}">
            <xen:hint>{xen:phrase iwd_if_enabled_random_treasures_will_be_turned_on}</xen:hint>
        </xen:option>
    </xen:checkboxunit>

Create a listener for Templates to pre-load and then add in your forum options template:
Code:
<?php
 
class IcewindDaleRP_IcewindDale_Listener_Template
{
    public static function template_create(&$templateName, array &$params, XenForo_Template_Abstract $template)
    {
        switch ($templateName)
        {
            case 'forum_edit':
                $template->preloadTemplate('iwd_forum_xp_modifiers');
            break;
        }
    }
   
    public static function template_hook($name, &$contents, array $hookParams, XenForo_Template_Abstract $template)
    {
        switch ($name)
        {
            case 'admin_forum_edit_forum_options':
                $xpmOptionsModel = XenForo_Model::create('IcewindDaleRP_IcewindDale_Model_Options');
 
                $params = $template->getParams();
                if (!empty($params['forum']['node_id']))
                {
                    $xpModOptions = $xpmOptionsModel->getForumXpModOptions($params['forum']['node_id']);
                }
                else
                {
                    $xpModOptions = $xpmOptionsModel->getForumXpModDefaults();
                }
 
                $contents .= $template->create('iwd_forum_xp_modifiers', array(
                    'xpModOptions' => $xpModOptions))->render();
            break;
        }
    }
}

Create a loadClassController listener to listen for Xenforo_ControllerAdmin_Forum
Code:
<?php
 
class IcewindDaleRP_IcewindDale_Listener_LoadClassController
{
        public static function loadClassListener($class, &$extend)
        {
        switch ($class)
        {
                    case 'XenForo_ControllerAdmin_Forum':
                $extend[] = 'IcewindDaleRP_IcewindDale_ControllerAdmin_Forum';
            break;
                }
        }
}

Create your custom load class controller for above:
Code:
<?php
 
class IcewindDaleRP_IcewindDale_ControllerAdmin_Forum extends XFCP_IcewindDaleRP_IcewindDale_ControllerAdmin_Forum
{
    public function actionSave()
    {
        $response = parent::actionSave();
        if ($response->redirectType == XenForo_ControllerResponse_Redirect::SUCCESS)
        {
            $xpmData = $this->_input->filter(array(
                'node_id' => XenForo_Input::UINT,
                'xp_mod' => XenForo_Input::UINT,
                'gold_mod' => XenForo_Input::UINT,
                'encounter' => XenForo_Input::UINT,
                'trap' => XenForo_Input::UINT,
                'treasure' => XenForo_Input::UINT
            ));
           
            if (empty($xpmData['node_id']))
            {
                $xpmData['node_id'] = $this->_getLastSavedForumNodeId();
            }
   
            $dw = XenForo_DataWriter::create('IcewindDaleRP_IcewindDale_DataWriter_Forum');
           
            $xpmOptionsModel = $this->_getForumXpModOptionsModel();
            if ($xpmOptionsModel->verifyForumXpModId($xpmData['node_id']))
            {
                $dw->setExistingData($xpmData['node_id']);
            }
 
            $dw->bulkSet($xpmData);
            $dw->save();
           
            $xpmOptionsModel->rebuildForumXpModCache();
        }
 
        return $response;
    }
   
    public function actionDelete()
    {
        $parent = parent::actionDelete();
 
        $this->_getForumXpModOptionsModel()->removeDeletedForums();
 
        return $parent;
    }
   
    public function actionValidateField()
    {
        $parentResponse = parent::actionValidateField();
 
        $fieldName = $this->_input->filterSingle('name', XenForo_Input::STRING);
        if ($fieldName == 'xp_mod' OR $fieldName == 'gold_mod')
        {
            $xpmResponse = $this->_validateField('IcewindDaleRP_IcewindDale_DataWriter_Forum', array(
                'existingDataKey' => $this->_input->filterSingle('node_id', XenForo_Input::UINT)
            ));
 
            return $xpmResponse;
        }
        else
        {
            return $parentResponse;
        }
    }
   
    protected function _getForumXpModOptionsModel()
    {
        return $this->getModelFromCache('IcewindDaleRP_IcewindDale_Model_Options');
    }
   
    protected function _getLastSavedForumNodeId()
    {
        return XenForo_Application::get('db')->fetchOne('
            SELECT node_id
            FROM xf_forum
            ORDER BY node_id
            DESC
        ');
    }
}

Create the data writer for your custom forum options:
Code:
<?php
 
class IcewindDaleRP_IcewindDale_DataWriter_Forum extends XenForo_DataWriter
{
    protected $_existingDataErrorPhrase = 'iwdrp_requested_forum_not_found';
 
    protected function _getFields()
    {
        return array(
            'iwdrp_forum_xp_mods' => array(
                    'node_id' => array('type' => self::TYPE_UINT, 'required' => true),
                    'xp_mod' => array('type' => self::TYPE_UINT, 'required' => true, 'default' => 78),
                    'gold_mod' => array('type' => self::TYPE_UINT, 'required' => true, 'default' => 100),
                    'encounter' => array('type' => self::TYPE_UINT, 'required' => true, 'default' => 1),
                    'trap' => array('type' => self::TYPE_UINT, 'required' => true, 'default' => 0),
                    'treasure' => array('type' => self::TYPE_UINT, 'required' => true, 'default' => 0)
            )
        );
    }
   
    protected function _getExistingData($data)
    {
        if (!$id = $this->_getExistingPrimaryKey($data, 'node_id', 'iwdrp_forum_xp_mods'))
        {
            return false;
        }
 
        return array('iwdrp_forum_xp_mods' => $this->_getForumXpModOptionsModel()->getForumXpModOptions($id));
    }
   
    protected function _getUpdateCondition($tableName)
    {
        return 'node_id = ' . $this->_db->quote($this->getExisting('node_id'));
    }
 
    protected function _postSave()
    {
        $this->_rebuildXPMCache();
    }
 
    protected function _postDelete()
    {
        $this->_rebuildXPMCache();
    }
 
    protected function _rebuildXPMCache()
    {
        $this->_getForumXpModOptionsModel()->rebuildForumXpModCache();
    }
 
    protected function _getForumXpModOptionsModel()
    {
        return $this->getModelFromCache('IcewindDaleRP_IcewindDale_Model_Options');
    }
}

and the result is this:
forumOptionsExample.webp
 
Thanks for your answers. There are basically the same so I use the template->create() function to get what I want. Special thanks to "Lawrence" for the detailed answer.
 
Top Bottom