Best Way to do this? FirstVisit Start Page

I'm about to write what I think should be a fairly simple module for someone to allow the Admin to define two start pages for their users. One for the first login after sign up (could be a welcome letter, ect) and the other start page would be a normal start page.

My thought is that the best way to achieve this without having to actually hack the existing routines is to:

1. Add a new field to the *_users table called first_vist or something that will default to 1. In the init set existing users to '0' (maybe admin selectable?) I've done similar wiht the new Groups module I'm almost done with for the same client and the regular NS-Groups works fine since it just ignores the extra fields, so It doesn't seem like it should cause a problem (unless the upgrade routine would get rid of the field in any upgrades).

2. Add two module vars for FirstVisit & Visit containing the URLs/Mods to use.

3. Admin has to set the pnFirstVisit as the start module.

What I'm thinking is that, in the init, I can get the value of the current startpage from the DB, assign that to the regular visitor value, and then change the start page to pnFirstVisit, since if the Admin is installing it, that means they plan to use it, and if it's not the start page, then it's worthless.

So, is there a better way to handle this? And do I need to define the new nuke_users structure in the pntables.php for the module since a field is added, or can I just add it using the init?
Don't have a clue how to do it, but I like the idea!
Michael,

Better to use a dynamic user data field to store the value for each user. Store the value using pnUserSetVar and retreive it with pnUserGetVar. User vars could store the visit times as well.

-Mark

--
Visit My homepage and Zikula themes.
IMHO to do it properly, a module with its own table is needed. In this table, only the usernames/uids are required. If the current user is contained in this table, redirect him to module "NotFirstVisit". If he is not, add him and redirect him to "FirstVisit". So this functionality is self-contained without being dependent on dynamic user data or hacking the user table.

I wouldn't set such a module as the start module, but to alter the login fields to redirect to this module after logging in.

Jörg
Mark, thanks. Makes sense that way. I'm assuming that would have the same effect as if I were to add a new field in that it could be set to 1 by default and updated to 0 on init for existing users?

Jörg, if I'm not mistaken, that would then require a hack to the core code to accomplish, which is what I'm trying to avoid. Is there some way what you suggest can be accomplished plug & play?

--
Home Page | Find on Facebook | Follow on Twitter
Oh and N!cklas, the cool thing is the client is planing to let me release this GPL and/or for submission to core. (Which if that's the case then I can see doing it Jörg's way since it'd be in the form of a patch I guess).

--
Home Page | Find on Facebook | Follow on Twitter
Jörg's method of using a dedicated table looks like the easier of the two to implement for the purpose of making it easy to install, since Mark's method would require adding a define to global.php, which is more work than I'd like to make the admin do. (Which is the only reason I want to do it as a stand alone module rather than a hack to the core. Maybe I'll submit as a patch for .8 once I get a good look at it).

--
Home Page | Find on Facebook | Follow on Twitter

mhalbrook

Jörg, if I'm not mistaken, that would then require a hack to the core code to accomplish, which is what I'm trying to avoid. Is there some way what you suggest can be accomplished plug & play?

You mean the second part of my suggestion, to alter the login fields?

This is why I not wrote where to change this, only what to change icon_rolleyes -- There are may ways wher you could log in. In can be in your theme, it can be done with the login block (whcih has indeed to be modified; but this can be done by copying the block and renaming it), or with user.php (in this case you would have to hack indeed).

I guess that for user friendlyness you are using one of the first two methods....

Technically, all you have to pass to the login procedure is a hidden field in the login form with the name URL and the value "where to go after logging in".

Jörg
Jörg, I did mean the 2nd part. Don't all methods of logging in ultimatly go through user.php? So the change would need to be made there I would think.

I'll have to see what my client thinks. I do know his desire/intent was something that could be submitted to be added to the core, which makes that a more attractive way to go. It's not really something that would need to be a seperate module in that case, just an extra couple lines of code in the user.php and the settings page.

--
Home Page | Find on Facebook | Follow on Twitter

mhalbrook

Don't all methods of logging in ultimatly go through user.php? So the change would need to be made there I would think.
No need to hack anything....

Have a look in modules/NS-User/user.php, function user_user_login(). You can see that the variable $URL ist taken from the input and passed to access_user_login, which is defined in modules/NS-User/user/access.php. There, this variable is passed to redirect_index defined in modules/NS-User/tools.php (uh, a long way to get there icon_rolleyes )

This variable is used to create the output

Code

echo "<html><head><META HTTP-EQUIV=Refresh CONTENT=\"2; URL=$url\">\n";


The only trick is to get the URL set in the login form. That is why I mentioned the different ways to get such a login form.

The form must look like

Code

<form action="user.php" method="post">
    Username: <input type="text" name="uname">
    Password: <input type="password" name="pass">
    <input type="checkbox" value="1" name="rememberme"> Remember me
    <input type="hidden" name="module" value="NS-User">
    <input type="hidden" name="op" value="login">
    <input type="hidden" name="url" value="http://www.example.com/index.php?module=MyFirstVisit">
    <input type="submit" value="Login">
</form>


Note the hidden URL field.

This can be hardcoded in the theme, in a block or elsewhere....
Jörg
Wouldn't it be better, in the initialization of the module (or if it's in the core of PostNuke) to do something like

Code

pnConfigSetVar('UseFirst','1');
pnConfigSetVar('FirstURL','....');
pnUserSetVar('FirstVisit','1');


Then add in to access.php

Code

if pnConfigGetVar('UseFirst')==1 and pnUserSetVar ('FirstVisit')!= '1' {
$url=pnConfigGetVar('FirstURL);
pnUserSetVar('
FirstVisit','1');
}
 rest of code


That way it wouldn't matter how the user logged in, the $URL value is over ridden if it's the user's first visit, otherwise it's what was set by the system.
I'm not clear on how to utilize the UserSetVar and UserGetVar, but I'm assuming it's best to check if it's set and if it isn't assume first visit?
Hey, you're hacking core :P

Of course that is the best way to do it, if it is not the first time the "normal" behaviour of the login procedure -- taking the now-logged-in user to where he was before -- is only altered for the first time. I'm too lazy at the moment to check if you can use pnUserGetVar this way, but I guess you can.

(looks to me we need something like userlogin and userlogout Hooks...)

Jörg
Oh :P. As I said, the client is interested in having this patch/module added to core, and it seems like it would be of no impact to people not wanting to use it (have it off by default) and very useful to those who find it a good idea.

--
Home Page | Find on Facebook | Follow on Twitter
I thought about something like

Code

pnModRegisterHook('user',
                           'login',
                           'API',
                           'MyModule',
                           'user',
                           'Func')
To be thought about icon_biggrin
Well, the part about checking if the admin has it on or off is working, just gotta figure out how to make use of userGetVar/SetVar if it can be done. I guess I need to add the Dynamic User Data when I install the module. If there's no display needed I guess the lang define doesn't need to be done?

--
Home Page | Find on Facebook | Follow on Twitter
Michael,

This won't help for .726 but for .8 there is a dynamic user data module with API's to add, delete etc. DUD properties so you'd be able to call the create API during your init script.

-Mark

--
Visit My homepage and Zikula themes.
Cool, I won't submit that as a feature request then :)

Is there anyway to do it in 726? I know where the DUD fields are stored, but where's the data for those fields stored, and how would I reference it as a value check?

--
Home Page | Find on Facebook | Follow on Twitter
The actual data is stored in <prefix>_user_property but the API's pnUserSetVar and pnUserGetVar should be used to read and write these settings - there's no need to interact directly with the table itself.

-Mark

--
Visit My homepage and Zikula themes.</prefix>
So, if I put

Code

pnUserSetVar('pnFirstVist','1');

In the init routines, that should create the nessecary field in the right place?

THe field itself is stored in user_property and the data for that field in user_data right?

--
Home Page | Find on Facebook | Follow on Twitter
My previous post should have read <prefix>_user_data - sorry my fault....

But apart fron that typo the answer to your question is yes but only if the DUD property 'pnFirstVisit' is known in the DUD property table - this is the problem with the .7x series the system's API's weren't finished.

You can read and write a setting but only once the setting has been created so your init script would need to talk directly to the dud property table to create the property but once that has been done what you have works.

I can see how this lack of a creation API came about as there is the potential duplication of DUD property names and no rules in place to govern naming of these.

-Mark

--
Visit My homepage and Zikula themes.</prefix>
Hmm, user_property doesn't have a field for a var name, so how would the system know to store something as pnFirstVisit in the user's data?

--
Home Page | Find on Facebook | Follow on Twitter
Michael,

<prefix>_user_property holds the structure of the DUD property not the values themselves. <prefix>_user_data holds the values themselves using prop_id to identify which property the users value refers too.

pnUserSetVar first checks the property table to check for a valid property name and in the process grabs the property id as well. This property id is then used to write the value for the variable into the data table. pnUserGetVar does the same except for a read on the data table in the last step. All of the code for the User API's are in includes/pnUser.php.

-Mark

--
Visit My homepage and Zikula themes.</prefix></prefix>
What I'm not understanding is where the system finds out that pnUserGetVar('pnFirstVisit') is refering to DUD 17.
<prefix>_user_property stores an id and a label, no name.

The label is a language define.</prefix>
I see - If you look at the pnUserGetVar code 'pnFirstVisit' is the property label. The current definitions use contant defines so they can be multi-lingual in the user interface but this isn't a strict requirement for the property. I suppose property 'label' really should read 'name' to be clearer.

So you define a new DUD property with the label being pnFirstVisit. The Set/Get API's then get the prop_id where prop_label is 'pnFirstVisit' and set the value with the prop_id.

-Mark

--
Visit My homepage and Zikula themes.
Yeah, I just figured that out looking closer at the way the pnUserSetVar function works. Now if there's away to make that a hidden field that the user can't edit in their profile, all is perfect :)

--
Home Page | Find on Facebook | Follow on Twitter
You can if using the pnUserHack as there is field for administrative purposes only. However given this overrides the users module then you loose some of features added in .726.

I've begun adding these kind of features based on pncUserHack and this patch. I'll be working through these over the next week.

-Mark

--
Visit My homepage and Zikula themes.
Nice to know that parts of pnUserHack will be added in. I think some of it was added in to 726 wasn't it?

Thanks for the help, again. So, should I put this in as a patch, or what? Since it's a combo patch and module at this point. The client that I'm doing this for felt that it would potentially be a good thing to add back in to the core system. Doesn't matter to me, since this is the same client I wrote the new groups module for and that too more work than I estimated, this ends up a freebie and then some, but both projects are green lighted by him to go back in to the community either added to core or available.

--
Home Page | Find on Facebook | Follow on Twitter
A few things we're. I'm look after the DUD side of things as this has been broken out into a distinct DynamicUserData module rather than part of the users module. Xiaoyu (class007) is looking after the user aspects.

For submission I would hold on to the code for the moment (or release it seperately for .726) until .8 is more stable - we're still coding at the moment. Keep me in the loop (send me the code) so that we can attempt to make sure that the only code you need is the module itself.

I look at this as a good oppurtunity to ensure that we have all the need routes into the core (via APIs etc. ) that you as a developer need to produce your module - a module should stand alone. I'm keen to work with other developers in this fashion to highlight and address any deficiencies in the core code. API compliance is a big step towards this but there are no doubt other areas that can be improved on.

-Mark

--
Visit My homepage and Zikula themes.
Okay, I have all 3 variables needed (On/Off flag for the function, URL to go to & pnFirstVisit user variable). Here's the modified access_user_login from NS-User/user/access.php

Code

function access_user_login($uname, $pass, $url, $rememberme)
{
   
/*Begin FirstVisit Mod*/
if (pnConfigGetVar('pnFirstVisitOn') =='1' AND !pnUserGetVar('FirstVisit')){
 $url = pnConfigGetVar('pnFirstURL');
}
/*End FirstVisit Mod*/

    if (pnUserLogIn($uname, $pass, $rememberme)) {
        redirect_index(_LOGGINGYOU, $url);
    } else {
        pnRedirect('user.php?stop=1');
    }
}

But it's not working it seems.
Michael,

I'll setup a test and debug this code on a test site later today.

-Mark

--
Visit My homepage and Zikula themes.
I figured it out. Had to go betwen the pnUserLogIn and the redirect.

It works pretty well. The Admin has to define the target URL as an actual URL, because it's conceivable that the Admin would want to send the user to a specific item in a module rather than to the module itself, and I don't think there's an easy way to do it other wise. But it works.

--
Home Page | Find on Facebook | Follow on Twitter
Mark, Michael, what about the suggestion to put there a generic solution? Something like a hook; as this could be used for other things as well (sending admin-mail for example)

Jörg
I'm not clear on the hook thing, so maybe Mark can address that. Where would a hook for this come in to play?

--
Home Page | Find on Facebook | Follow on Twitter
My idea is as follows: We have several "user events": registration, logging in, logging out, maybe even more. A module could register to these events (just like the hook thing now), and when some of these events occur, the registered function is fired.
Makes sense?
Jorg,

See my comments in this thread for my thoughts on some account management hooks as a method to 'bridge' third party apps but are equally relevant here.

-Mark

--
Visit My homepage and Zikula themes.
Ah! Sometimes I should have a look in the forums, even if the main subject is of no interest to me :mrgreen:

May I ask how far you got right now?

Jörg
Jorg,

Early planning stages - although the concept seems sound. The main issue currently comes down to time. I need to spend some time writing a bridge module to a third party application to prove that the theory translates into practice. I don't want to include hook calls in the code that I haven't proved deliver on thier aims. Even though this wouldn't impact of operability of the product itself it does put into a place requirements for a support mechanism on some code that doesn't necessarily function as required.

-Mark

--
Visit My homepage and Zikula themes.
Hi Mark,

I definitely want to be involved with this to make sure that X-User will continue to work with the hook calls. If you need anything from me, please let me know.

Co
Coho,

Drop me an e-mail to markwest at postnuke dot com so I have a valid e-mail address. This is something i've been thinking on for about six months so the concepts are sound. If I do it right then there should be no impact on any third party at all. It will simply be an option that is available. I'd like to get these hook calls into PN .8 but as i've said elsewhere this is dependant on me having sufficient development time to 'port' an application as a test.

I believe this will work and work well but need more than that to fufill my own personal requirements for a solution.

-Mark

--
Visit My homepage and Zikula themes.
OK - Will do.
This discussion is a bit above me, but I think it may help with a problem I have. Please let me know if it will.

I have a couple of generic user accounts (one for students and one for parents) and I do not want them to do most of the functions in user.php (Add comments to their profile, change homepage, change password)

I have set the permissions so they can not access user.php via the My Account menu item. I have also added a hack so they can not access their profile thru pnPHPBB2.

It still defaults to user.php the first time they login on a new computer (I think this part is true .... (on a new computer").

Is this a result of a first visit to the portal? ... from a new computer?

What might I modify to prevent these 2 users (group name: ViewOnly) from accessing user.php?

thanks in advance
It is often a problem to get a third party module to recognize a user registered at the site. examples are pnTresmailer and at least some of the forum modules.
It would be convenient for some sites to have the first visit process register the user with one or more modules, as an option.
I could see how that'd be useful, but not very easy to do. It would require putting in code to check for all the modules that this is an issue for and running it. Though this, along with pnGroups & some other things I have in mind for pnGroups could tie together for a totally revamped user system. If I do get that ambitious, I'll do it like I did pnGroups where it doesn't change any existing data structures, but may add in fields.

--
Home Page | Find on Facebook | Follow on Twitter