1.8 - Current username

Hello,

I have a question about how to get the current username.

I have to use it to make an url to get a xml file for a module.

So, how can I get the username ?
I have tried $_session[‘username’] but it doesn’t work.

If you are inside module code, you can use:

$this->getUser()->userName;

I’m in a module, but when I try to display the user name in a region for test, I only get an error message with your code :confused:

Another way to do what I want, is to edit the user table in the database, but I have to know if next update will erase all changes I’ll make.

Can you provide a code example please?

You shouldn’t edit the user name directly or change its structure - if you do that you’ll never be able to upgrade

Of course, about the user name, all accounts will be like ‘City_com’. Here, the account is Dijon_com and to get the good XML, I have “cut” the city in the user name.
It’s the most simply way I found to do this without change the database

public function getUser(){
    		$user = $this->getUser()->userName;
    		$ville = explode('_', $user);
    		
    		$url = 'http://irestos.fr/xml/'.$ville[0].'_menu.xml';
    		return $url;
    	}
    	
    	public function getContenu(){
    		
    		//$url = 'http://localhost/stage/prototype/xml/dijon_menu_base.xml';
    		//$url = 'https://irestos.nuonet.fr/xml/dijon_menu.xml';
    		$urlFinale = $this->getInvolve();
    		$client = new Client();
    
            try {
                $tryTo = $client->get($urlFinale, Config::getGuzzleProxy());
    
                if ($tryTo->getStatusCode() == 200) {
    				$toJson = $tryTo->getBody();
    				
    				return $toJson;
                }
                else {
                    Log::info('Non %d. %s', $tryTo->getStatusCode(), $tryTo->getBody());
                    return false;
                }
            }
            catch (RequestException $e) {
                Log::error('Impossible de joindre iResto: %s', $e->getMessage());
                return false;
            }
    	}

And in getResource:

$menu = $this->parseLibraryReferences($isPreview, $this->getContenu());

I think the fundamental problem with that is that when a display calls GetResource in order to display content, there won’t be a user account at all.

I.e. at best this will only ever work in the CMS Preview and Layout Designer.

Wouldn’t you want to use the display name instead? In which case the $displayId is passed into getResource?

So, I can’t get the username in ‘getUser’ to add his name in the final url even if I do this before calling the getRessource ?

I get an error in the code I gave you yesterday at $urlFinale = $this->getInvolve(); It should be $this->getUser(); to get the real url.

The purpose of this module is to get informations about university restaurants menu from a xml created by city (city have more than one restaurant) and display it in a region.

Basicaly, the module must check current user’s to make a dropdown list in the add form according it’s city (it’s the reason why account have a name like ‘Dijon_com’) to allow user to choose which menu must be display for this layout.

getResource will be called by the Player (by XMDS actually) and won’t have the same userId as the one who created the Layout in the first place. You can’t even guarantee that the user whom created the layout is the same person that will edit it, etc.

You can call getUser in add() and edit() to create your drop down list, but you should save the result as an option $this->setOption('menuSelection', Sanitize::getParam('myfieldname')); and then in getResource() you should retrieve it $menu = $this->getOption('menuSelection');

Ok, I was thinking getResource could find the current user name. I’ll use the display name.

But now, in my twig form, is it possible to use template_from_string() to generate a dropdown list from a twig extension ?
The purpose of this extension is to generate a dropdown list according the current user name (Dijon_Com could only get display from restaurant in Dijon)

I’m completely confused now :smiley:

Your problem statement is:

  • The user name of each user determines which options they should have in a drop down list
  • The options the user selected when they create their widget should be shown in get resource

If that is the case I would do as previously suggested:

  • Load your add/edit forms with the drop down list based on the current user. The best way to do that would be to override setTemplateData in your widget class and use that to set your dropdown list content in a variable. Something like:
   /**
     * Set template data
     * @param array $data
     * @return array
     */
    public function setTemplateData($data)
    {
        $dropDownContent = $this->getDropDownContentBasedOnUser();
        return array_merge($data, ['dropdown' => $dropDownContent]);
    }
  • Save the users selection in an option
$this->setOption('menuSelection', Sanitize::getParam('myfieldname'));
  • Load the option in getResource
$menu = $this->getOption('menuSelection');

I think the most important problem is I don’t really understand how xibo work (and maybe because I’m not a fully qualified developer but a student) :confused:

I’ll try to explain more clearly what I have to do (I’m not quite good in english :confused:):

The module (called iRestos) have to get a XML file located in other server to display its informations.

This XML contains all menus for all restaurants for a city (there is 28 XML files)

To make this module more “user friendly” (it will be used by different cities’s communication services), I want to make a drop down list which contains all restaurant to let user choose the menu must be display in this layout.
All cities’s communication services have a username like “City_com”.

I would like to use this user name to define the drop down list (Dijon doesn’t need to get Paris’s menus).

But I have no idea about how can I do this. I tried to make a json file with all restaurants by cities but this doesn’t work. For now, I just have a module that can display informations from a xml and an empty drop down list :disappointed_relieved:

I try your code all along the day with some experiments using the Finance module but no result :worried:

Oh and sorry for the longer of this post :no_mouth:

add-form.twig

{% set title %}{% trans "Restaurant" %}{% endset %}
{% set helpText %}{% trans "Quel restaurant ?" %}{% endset %}
{{ forms.dropdown("Restaurants", "single", title,module.getOption("restaurants"), module.restosDispo(),"nom", "value", helptext)}}

iResto.php

private function loadTemplates()
    {
        $this->module->settings['restaurant'] = [];

        // Scan the folder for template files
        /*foreach (glob(PROJECT_ROOT . '/modules/iresto/*-restaurants.json') as $resto) {
            // Read the contents, json_decode and add to the array
            $this->module->settings['restaurant'][] = json_decode(file_get_contents($resto), true);
        }*/
        
        $this->module->settings['restaurant'][] = json_decode(file_get_contents(PROJECT_ROOT.'/modules/iresto/dijon.json'), true);

        Log::debug(count($this->module->settings['restaurant']));
    }
    
    public function restosDispo(){   
        if (!isset($this->module->settings['restaurant']))
            $this->loadTemplates();

        return $this->module->settings['restaurant'];
    }

public function add()
    {   
        //$user = $this->getUser()->userName;
        
        // Formulaire
        
        $this->setDuration(Sanitize::getInt('duration'));
        $this->setOption('name', Sanitize::getString('name'));
        $this->setOption('restaurants', Sanitize::getString('restaurants'));

        // Save the widget
        $this->validate();
        $this->saveWidget();
    }

    public function urlDefine(){
        $restaurant = $this->getOption('restaurants'); 
        
        /*  * Experimental 
            * try with 2 cities
        */
        switch ($restaurant){
            case 'Montmuzard':
            case 'Mansart':
                //$cityName = 'dijon';
                $url = 'http://irestos.nuonet.fr/xml/dijon_menu.xml';
                return $url;
                break;
            case 'Poit':
            case 'Tiers':
                //$cityName = 'poitiers';
                $url = 'http://irestos.nuonet.fr/xml/poitiers_menu.xml';
                return $url;
                break;
            default:
                $url = 'http://localhost/stage/prototype/xml/fail.xml';
                return $url;
        }
	}
	
	public function getMenu(){
		
		$urlFinale = $this->urlDefine();
		$client = new Client();

        try {
            $tryTo = $client->get($urlFinale, Config::getGuzzleProxy());

            if ($tryTo->getStatusCode() == 200) {
				$xmlContent = $tryTo->getBody();
				
				return $xmlContent;
            }
            else {
                Log::info('Non %d. %s', $tryTo->getStatusCode(), $tryTo->getBody());
                return false;
            }
        }
        catch (RequestException $e) {
            Log::error('Impossible de joindre iResto: %s', $e->getMessage());
            return false;
        }
	}

I feel your pain, but at the same time don’t have the resources to write it for you. I think you are quite close - i’ve made some changes to your code below - see if you understand them.

Please add more comments to your code :smiley:

/**
 * You need a place to store your city information - this could be in a dataset or in a JSON file, etc.
 *   I've created an array with the username as the key and the URL as the value.
 */
private static $cities = [
        'dijon_com' => 'http://irestos.nuonet.fr/xml/dijon_menu.xml',
        'poitiers_com' => 'http://irestos.nuonet.fr/xml/poitiers_menu.xml',
    ];

/**
 * Resolve the 
 */
public function restosDispo() {

    // Resolve the user name
    // Use either the stored one (we add this in add - or if that hasn't happened yet, use the logged in one)
    //  *edge case* - different users open the edit form! 
    $userName = $this->getOption('userName', $this->getUser()->userName);

    // This function is called by your Twig Template when you want to get the possible options for the drop down
    // Get the appropriate XML file
    $xmlUrl = $this->cities[$userName];

    // Get the Contents of the XML file
    $xml = $this->getMenu($xmlUrl);

    // Parse the XML and create an array like:
    return [
        ['nom' => 'CITY_ID', 'value' => 'Friendly City Name']
    ];
}

public function add()
    {   
        //$user = $this->getUser()->userName;
        
        // Formulaire
        
        $this->setDuration(Sanitize::getInt('duration'));
        $this->setOption('name', Sanitize::getString('name'));

        // Store the username of the person who created this for easy lookup on edit
        // You could call this option "city" instead
        $this->setOption('userName', $this->getUser()->userName);

        // In my opinion this would be better named "restaurant" as you will only get one - but hey ho
        $this->setOption('restaurants', Sanitize::getString('restaurants'));

        // Save the widget
        $this->validate();
        $this->saveWidget();
    }

	public function getMenu($urlFinale) {
		
		$client = new Client();

        try {
            $tryTo = $client->get($urlFinale, Config::getGuzzleProxy());

            if ($tryTo->getStatusCode() == 200) {
				$xmlContent = $tryTo->getBody();
				
				return $xmlContent;
            }
            else {
                Log::info('Non %d. %s', $tryTo->getStatusCode(), $tryTo->getBody());
                return false;
            }
        }
        catch (RequestException $e) {
            Log::error('Impossible de joindre iResto: %s', $e->getMessage());
            return false;
        }
}

Thanks a lot Dan ! It’s almost done ! :grinning:

I have one last problem to finish this module and of course, it’s around the user name.

Even if add $this->setOption('city', $this->getUser()->userName); in add() and try to get it in other function by $username = $this->getOption('city');

I get this error in the log entries:
An exception has been thrown during the rendering of a template ("Undefined index: ") in “iresto-form-add.twig” at line 45. Exception Type: Twig_Error_Runtime

It’s seems the city option is empty, so maybe it’s possible to give the username as argument directly when the function is called in the Twig file ?

Maybe something like:

{{ forms.dropdown("restaurant", "single", title, module.getOption("restaurant"), module.restosDispo(currentUser.userName),"nom", "value", helptext)}}

*Oh and I promess I’ll add more comments in my code :sweat_smile: *

Looks like you have made some progress!

Your problem is that the module does not have access to the user during the add form process - I am not sure why really. As you have said a good workaround would be to provide the current user to the restosDispo function.

You would need to change the method signature for that to:

public function restosDispo($userName) {}

and of course remove the section where we get the username from options.

This call would be right for the add-form - the edit form would be

module.restosDispo(module.getOption("userName"))

I think you’ve got it!

haha, good! :blush:

Thank you Dan, the module is working and it’s ready to get tested by the communication service (and also by my traineeship supervisor) ! :smile:

1 Like

Fantastic - I am pleased you have something working!

1 Like