Where does the 'tag_id' come from?

TheBigK

Well-known member
I'm looking at this action in the XenForo_ControllerAdmin_Tag :
PHP:
public function actionDelete()
    {
        if ($this->isConfirmedPost())
        {
            return $this->_deleteData(
                'XenForo_DataWriter_Tag', 'tag_id',
                XenForo_Link::buildAdminLink('tags')
            );
        }
        else
        {
            $tagId = $this->_input->filterSingle('tag_id', XenForo_Input::UINT);
            $tag = $this->_getTagOrError($tagId);

            $viewParams = array(
                'tag' => $tag
            );

            return $this->responseView('XenForo_ViewAdmin_Tag_Delete', 'tag_delete', $viewParams);
        }
    }

I'm wondering where is the 'tag_id' field in the XenForo_Input? I mean, I don't see any template (specifically tag_delete) defining it? How does XenForo know which tag I'm deleting?
 
I mean, I don't see any template (specifically tag_delete) defining it?
Well.. that'd be because templates don't define variables?

As @Jake B. said, it's coming from the url. If you need to know more about that, then you need to dig through the code and see how XenForo's routing system works (start with XenForo_Route_PrefixAdmin_Tags::match()).
 
Well.. that'd be because templates don't define variables?

As @Jake B. said, it's coming from the url. If you need to know more about that, then you need to dig through the code and see how XenForo's routing system works (start with XenForo_Route_PrefixAdmin_Tags::match()).
So far I've been thinking that the XenForo_Input would get only the variables in the forms [still getting used to the way things work in XF]. Now it looks like it's getting stuff from the URL.

I'm building a similar addon and discovered that my 'delete' button does not show the ID in the URL. I also checked the match() function and found that it's got this extra thing: -

$action = $router->resolveActionWithIntegerParam($routePath, $request, 'tag_id');

It's something totally new to me; and I've no clue at this time how it's generating a tag_id.
 
If you pop open the XenForo_Route_PrefixAdmin_Tags class you'll see that essentially it's telling the XenForo router that any integer passed in with the link should be treated as the tag_id.

So then, line 6 of the tag_delete template has the form action set to '{xen:adminlink tags/delete, $tag}'. What this does is send the contents of $tag (which would include tag_id) to the admin link helper which tries to form a link based on the route 'tags'. The route class I mentioned earlier tells XenForo that it needs an integer with the name 'tag_id' to be able to form the URL with that parameter. As the entire contents of $tag were sent, which include tag_id, that's where it comes from. XenForo_Input then lets you filter that URL parameter.

I think I've explained that right, or at least to the best of my knowledge. Someone else can clarify if I made a mistake anywhere or missed out a detail but that's roughly how it works, I believe.
 
So far I've been thinking that the XenForo_Input would get only the variables in the forms [still getting used to the way things work in XF]. Now it looks like it's getting stuff from the URL.
XenForo_Input::filterSingle()
line 180 (important line as it appears to be where it grabs the data from)
PHP:
$data = $this->_request->getParam($variableName);

Assuming you're using an IDE hold control and click getParam (or the mac alternative, not sure):
Leads to Zend_Controller_Request_Http::getParam()

PHP:
public function getParam($key, $default = null)
    {
        $keyName = (null !== ($alias = $this->getAlias($key))) ? $alias : $key;

        $paramSources = $this->getParamSources();
        if (isset($this->_params[$keyName])) {
            return $this->_params[$keyName];
        } elseif (in_array('_GET', $paramSources) && (isset($_GET[$keyName]))) {
            return $_GET[$keyName];
        } elseif (in_array('_POST', $paramSources) && (isset($_POST[$keyName]))) {
            return $_POST[$keyName];
        }

        return $default;
    }

This tells us, it'll return the variable if it's found in the param list that was manually set, if there isn't one, it returns the variable from the url, if it isn't there it returns it from the form ($_POST).

The easiest way to answer your questions regarding basic functionality that is used everywhere is to look in the code.

$action = $router->resolveActionWithIntegerParam($routePath, $request, 'tag_id');
Let's hold control and click the function name again and see where it goes... XenForo_Router::resolveActionWithIntegerParam()

PHP:
/**
    * Resolves the action from a route that looks like name.123/action and sets
    * the "123" param into the specified parameter name.
    *
    * Supports name.123/action1/action2 (returns "action1/action2"). If given
    * "action1/action2", this will return the full string as the action as long as action1
    * does not have a "." in it.
    *
    * @param string $routePath Full path to route against. This should not include a prefix.
    * @param Zend_Controller_Request_Http $request Request object
    * @param string $paramName Name of the parameter to be registered with the request object (if found)
    * @param string $defaultActionWithParam If there's no action and there is an int param, use this as the default action
    *
    * @return string The requested action
    */
    public function resolveActionWithIntegerParam($routePath, Zend_Controller_Request_Http $request, $paramName, $defaultActionWithParam = '')

So this says when you're looking at a url that's like /route/string.int/action, it's going to take string.int/action and set "int" as whatever the $paramName is (in your case "tag_id").

So now, $request->getParam('tag_id') = that {int} and XenForo_Input::filterSingle('tag_id', XenForo_Input::UINT); returns that int.

It's something totally new to me; and I've no clue at this time how it's generating a tag_id.
I think (and hope you will) you should take some time to learn how to use your IDE, if you aren't using an IDE then start. Learning how to navigate through all these functions and read what they do is the easiest way to learn how these things work.
 
So this says when you're looking at a url that's like /route/string.int/action, it's going to take string.int/action and set "int" as whatever the $paramName is (in your case "tag_id").
That's what I needed to know. Of course I followed a few things blindly; but now I have more clarity. Thanks a TON!

I am using phpStorm which is one of the top recommended IDEs here. Learning to use IDE is another challenge; but I'm now getting used to exploring function by checking their declarations.
 
That's what I use, ctrl + clicking = your friend.

Ooh, I didn't know that was a thing. I'm gonna have to use that, also discovered that I can apparently copy the entire reference to a function/variable in a class with Command+Option+Shift+C which I will never remember because Mac has to be ridiculous with their hotkeys. :|
 
Top Bottom